using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.MongoModels;
using MongoDB.Bson;

namespace adas_core.Application.Repositories.Interfaces;

public interface IConfigObservationRepository : IMongoRepository<ConfigObservation>
{
    /// <summary>
    /// Asynchronously retrieves a configuration observation by its unique identifier, returning <c>null</c> when no matching observation exists.
    /// </summary>
    /// <param name="id">The unique identifier of the configuration observation to locate.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the <see cref="ConfigObservation"/> if found, or <c>null</c> if no observation matches the specified identifier.</returns>
    Task<ConfigObservation?> FindById(ObjectId id);

    /// <summary>
    /// Updates an existing configuration observation in the underlying store.
    /// Returns the updated observation, or <c>null</c> when no matching observation is found.
    /// </summary>
    /// <param name="configObservation">The configuration observation containing the updated values to persist.</param>
    /// <returns>A task that resolves to the updated <see cref="ConfigObservation"/>, or <c>null</c> if the observation does not exist.</returns>
    Task<ConfigObservation?> Update(ConfigObservation configObservation);

    /// <summary>
    /// Deletes the configuration observation identified by the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the configuration observation to delete.</param>
    /// <returns>A task that represents the asynchronous delete operation. The task result contains the deleted configuration observation, or <c>null</c> if no observation with the specified identifier was found.</returns>
    Task<ConfigObservation?> Delete(ObjectId id);

    /// <summary>
    /// Asynchronously retrieves all available identifiers, returning them as a list of <see cref="ObjectId"/> values.
    /// </summary>
    /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous operation, containing a list of all <see cref="ObjectId"/> instances found.</returns>
    Task<List<ObjectId>> FindAllIds();

    /// <summary>
    /// Retrieves all configuration observations available in the system.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains a collection of <see cref="ConfigObservation"/> instances.</returns>
    Task<ICollection<ConfigObservation>> FindAll();

    /// <summary>
    /// Asynchronously retrieves a list of configuration names associated with the specified identifier.
    /// </summary>
    /// <param name="id">The identifier used to look up the configuration names.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of configuration names.</returns>
    Task<List<string>> GetConfigNames(string id);
    /// <summary>
    /// Asynchronously retrieves the list of available configuration names.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation, containing the list of configuration names.</returns>
    Task<List<string>> GetConfigNames();
    /// <summary>
    /// Asynchronously retrieves the total count of items.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation, containing the total count as a <see cref="long"/>.</returns>
    Task<long> Count();
    /// <summary>
    /// Retrieves a paginated collection of configuration observations based on the specified filter.
    /// </summary>
    /// <param name="filter">The pagination filter that defines the page size, page number, and any additional criteria used to retrieve the observations.</param>
    /// <returns>A task that represents the asynchronous operation, containing a collection of <see cref="ConfigObservation"/> items that match the pagination criteria.</returns>
    Task<ICollection<ConfigObservation>> GetPaginatedItems(PaginationFilter filter);
    /// <summary>
    /// Retrieves a configuration observation that matches the specified name.
    /// </summary>
    /// <param name="name">The name of the configuration observation to find.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the matching ConfigObservation if found; otherwise, null.</returns>
    Task<ConfigObservation?> FindByName(string name);
    /// <summary>
    /// Retrieves a <see cref="ConfigObservation"/> matching the specified coding system and code.
    /// </summary>
    /// <param name="codingSystem">The coding system identifier used to look up the configuration observation.</param>
    /// <param name="code">The code value within the specified coding system used to look up the configuration observation.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the matching <see cref="ConfigObservation"/> if found; otherwise, <c>null</c>.</returns>
    Task<ConfigObservation?> GetByCodeSysAndCode(string? codingSystem, string? code);
    /// <summary>
    /// Asynchronously inserts the specified configuration observation item and returns the persisted entity.
    /// </summary>
    /// <param name="configObservationItem">The configuration observation to insert.</param>
    /// <returns>A task that represents the asynchronous insert operation, containing the inserted <see cref="ConfigObservation"/>.</returns>
    Task<ConfigObservation> InsertOneAsyncAndReturn(ConfigObservation configObservationItem);
    /// <summary>
    /// Asynchronously retrieves all <see cref="ConfigObservation"/> records matching the specified name.
    /// </summary>
    /// <param name="name">The name used to look up the configuration observations.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains a list of <see cref="ConfigObservation"/> objects matching the given name, or an empty list if none are found.</returns>
    Task<List<ConfigObservation>> FindAllByName(string name);

    /// <summary>
    /// Retrieves a single <see cref="ConfigObservation"/> item matching the provided criteria, or <see langword="null"/> if no matching item is found.
    /// </summary>
    /// <param name="code">The code used to look up the configuration observation item, or <see langword="null"/> if not specified.</param>
    /// <param name="codingSystem">The coding system associated with the code, or <see langword="null"/> if not specified.</param>
    /// <param name="name">The name used to look up the configuration observation item, or <see langword="null"/> if not specified.</param>
    /// <param name="originalName">The original name used to look up the configuration observation item, or <see langword="null"/> if not specified.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the matching <see cref="ConfigObservation"/> item, or <see langword="null"/> if no item matches the specified criteria.</returns>
    Task<ConfigObservation?> GetSingleConfigObservationItem(string? code, string? codingSystem, string? name,
            string? originalName);
}