using adas_core.Domain.Enums;
using adas_core.Domain.Models.DTO;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.MongoModels;
using MongoDB.Bson;
using MongoDB.Driver;

namespace adas_core.Application.Repositories.Interfaces;

public interface IUnitRepository : IMongoRepository<Unit>
{
    //Task<Unit?> FindByLocation(PatientLocation location);
    /// <summary>
    /// Asynchronously retrieves a <see cref="Unit"/> entity by its identifier.
    /// </summary>
    /// <param name="id">The identifier of the <see cref="Unit"/> to locate.</param>
    /// <returns>A task that resolves to the matching <see cref="Unit"/>, or <c>null</c> if no entity is found.</returns>
    Task<Unit?> FindById(object id);

    /// <summary>
    /// Asynchronously finds a unit by its section name.
    /// </summary>
    /// <param name="section">The name of the section to search for.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the unit if found; otherwise, null.</returns>
    Task<Unit?> FindByName(string section);

    //Task<Unit?> FindByPointOfCare(PointOfCare pointOfCare);
    /// <summary>
    /// Asynchronously retrieves all available units and returns them as a list.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation, containing a list of all <see cref="Unit"/> entities.</returns>
    Task<List<Unit>> GetAll();
    /// <summary>
    /// Updates an existing unit in the underlying store and returns the updated entity.
    /// </summary>
    /// <param name="section">The unit containing the updated data to persist.</param>
    /// <returns>A task that resolves to the updated <see cref="Unit"/>, or <c>null</c> when the unit cannot be found.</returns>
    Task<Unit?> UpdateUnit(Unit section);
    /// <summary>
    /// Inserts a single <see cref="Unit"/> record and returns the inserted entity, or <see langword="null"/> if the insertion did not produce a result.
    /// </summary>
    /// <param name="unit">The <see cref="Unit"/> entity to insert.</param>
    /// <returns>A task that represents the asynchronous insert operation. The task result contains the inserted <see cref="Unit"/>, or <see langword="null"/> when no unit is returned.</returns>
    Task<Unit?> InsertOneUnit(Unit unit);
    /// <summary>
    /// Retrieves the collection of units associated with the specified master list identifier and master list type.
    /// </summary>
    /// <param name="id">The unique identifier of the master list whose units should be retrieved.</param>
    /// <param name="masterListType">The type of the master list used to filter or scope the unit lookup.</param>
    /// <returns>A task that represents the asynchronous operation, containing the collection of units linked to the specified master list.</returns>
    Task<IEnumerable<Unit>> FindByMasterListId(ObjectId id, MasterListType masterListType);
    /// <summary>
    /// Asynchronously retrieves the collection of <see cref="Unit"/> entities associated with the specified master list identifier.
    /// </summary>
    /// <param name="id">The <see cref="ObjectId"/> of the master list whose units are being requested.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="IEnumerable{Unit}"/> with the units linked to the given master list.</returns>
    Task<IEnumerable<Unit>> FindByMasterListId(ObjectId id);
    /// <summary>
    /// Updates the unit master list based on the provided unit identifiers. Returns the updated <see cref="Unit"/> when the operation succeeds, or <c>null</c> when no matching unit is found.
    /// </summary>
    /// <param name="updateUnitListDto">The data transfer object containing the list of unit identifiers to update.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the updated <see cref="Unit"/>, or <c>null</c> if no unit was updated.</returns>
    Task<Unit?> UpdateUnitMasterList(UpdateUnitIdListDto updateUnitListDto);
    /// <summary>
    /// Updates the name and title of an existing unit identified by the specified identifier.
    /// </summary>
    /// <param name="unitId">The unique identifier of the unit to update.</param>
    /// <param name="name">The new name to assign to the unit.</param>
    /// <param name="title">The new title to assign to the unit.</param>
    /// <returns>A task that represents the asynchronous update operation. The task result contains the updated <see cref="Unit"/>, or <c>null</c> if the unit was not found.</returns>
    Task<Unit?> UpdateUnitInfo(ObjectId unitId, string name, string title);
    /// <summary>
    /// Updates the configuration of a unit identified by the specified identifier.
    /// </summary>
    /// <param name="unitIdParsed">The parsed object identifier of the unit whose configuration will be updated.</param>
    /// <param name="unitConfiguration">The new configuration values to apply to the unit.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the configuration was successfully updated; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateConfiguration(ObjectId unitIdParsed, UnitConfiguration unitConfiguration);
    /// <summary>
    /// Retrieves a paginated collection of <see cref="Unit"/> records based on the provided pagination criteria.
    /// </summary>
    /// <param name="filter">The pagination filter that defines the page size, page number, and any additional filtering criteria.</param>
    /// <returns>An <see cref="IFindFluent{Unit, Unit}"/> representing the fluent query for the paginated units.</returns>
    IFindFluent<Unit, Unit> GetPaginatedUnits(PaginationFilter filter);
    /// <summary>
    /// Asynchronously counts the number of units associated with the master list identified by the specified identifier and type.
    /// </summary>
    /// <param name="id">The unique identifier of the master list whose units should be counted.</param>
    /// <param name="masterListType">The type of the master list used to resolve the appropriate unit collection.</param>
    /// <returns>A task that represents the asynchronous operation, containing the total number of units matching the specified master list.</returns>
    Task<long> CountUnitsByMasterListId(ObjectId id, MasterListType masterListType);
}