using adas_core.Domain.Models;
using adas_core.Domain.Models.DTO;
using adas_core.Domain.Models.Masters;
using adas_core.Domain.Models.MongoModels;
using MongoDB.Bson;

namespace adas_core.Application.Repositories.Interfaces;

public interface IAdmissionRepository : IMongoRepository<Admission>
{
    /// <summary>
    /// Deletes the entity identified by the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the entity to delete.</param>
    Task Delete(ObjectId id);

    /// <summary>
    /// Updates the specified admission record asynchronously.
    /// </summary>
    /// <param name="admission">The admission entity containing the updated information.</param>
    Task Update(Admission admission);

    /// <summary>
    /// Updates the location of an entity identified by the specified identifier to a new location.
    /// </summary>
    /// <param name="id">The unique identifier of the entity whose location is to be updated.</param>
    /// <param name="newLocation">The identifier of the new location to assign to the entity.</param>
    Task UpdateLocation(ObjectId id, ObjectId newLocation);

    /// <summary>
    /// Updates an existing patient record identified by the specified identifier with the provided patient information.
    /// </summary>
    /// <param name="id">The unique identifier of the patient to update.</param>
    /// <param name="patient">The patient object containing the updated information to apply.</param>
    Task UpdatePatient(ObjectId id, Person patient);

    /// <summary>
    /// Asynchronously retrieves all admission records.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="IEnumerable{Admission}"/> with all available admissions.</returns>
    Task<IEnumerable<Admission>> FindAll();

    /// <summary>
    /// Asynchronously retrieves an <see cref="Admission"/> entity by its unique identifier, returning <c>null</c> when no matching record is found.
    /// </summary>
    /// <param name="id">The <see cref="ObjectId"/> of the <see cref="Admission"/> to look up.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the matching <see cref="Admission"/>, or <c>null</c> if no admission exists with the specified identifier.</returns>
    Task<Admission?> FindById(ObjectId id);

    /// <summary>
    /// Retrieves an admission record that matches the specified NHC (Número de Historia Clínica) identifier, or <c>null</c> when no matching admission exists.
    /// </summary>
    /// <param name="nhc">The NHC (clinical history number) used to look up the admission.</param>
    /// <returns>A task that resolves to the matching <see cref="Admission"/>, or <c>null</c> if no admission is found for the given NHC.</returns>
    Task<Admission?> FindByNhc(string nhc);

    //Task<IEnumerable<Admission>?> FindByUnit(string unit);

    /// <summary>
    /// Asynchronously retrieves a list of admissions associated with the specified patient location.
    /// </summary>
    /// <param name="location">The patient location used to filter and find the relevant admissions.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of admissions matching the given location.</returns>
    Task<List<Admission>> FindByLocation(PatientLocation location);

    /// <summary>
    /// Asynchronously retrieves a collection of admissions filtered by the specified origin.
    /// </summary>
    /// <param name="origin">The origin value used to filter the admissions.</param>
    /// <returns>A task that represents the asynchronous operation, containing a collection of matching admissions, or <c>null</c> if no admissions are found for the given origin.</returns>
    Task<IEnumerable<Admission>?> FindByOrigin(string origin);
    /// <summary>
    /// Asynchronously inserts a new <see cref="Admission"/> record into the data store and returns the resulting entity.
    /// </summary>
    /// <param name="origin">The <see cref="Admission"/> entity to be inserted.</param>
    /// <returns>A task that represents the asynchronous insert operation, containing the inserted <see cref="Admission"/>, or <c>null</c> if no result is returned.</returns>
    Task<Admission?> InsertOneAsyncAndReturn(Admission origin);
    /// <summary>
    /// Searches for an admission matching the specified patient number and unit, returning a distinct result.
    /// </summary>
    /// <param name="patientNumber">The patient's identifier used to locate the admission.</param>
    /// <param name="unitId">The unique identifier of the unit to filter the search.</param>
    /// <returns>A <see cref="Admission"/> if a matching record is found; otherwise, <c>null</c>.</returns>
    Task<Admission?> SearchByPatientNumberAndDistinctUnit(string patientNumber, ObjectId unitId);
    /// <summary>
    /// Asynchronously retrieves a list of admissions associated with the specified unit, excluding Point of Care (PoC) entries.
    /// </summary>
    /// <param name="unitId">The unique identifier of the unit whose admissions are being retrieved.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of <see cref="Admission"/> records linked to the given unit, with PoC entries excluded.</returns>
    Task<List<Admission>> GetAdmissionByUnitIdWithOutPoC(ObjectId unitId);
    /// <summary>
    /// Retrieves a list of admissions associated with the specified point of care identifier.
    /// </summary>
    /// <param name="pocId">The unique identifier of the point of care used to filter the admissions.</param>
    /// <returns>A task that represents the asynchronous operation, containing the list of admissions matching the specified point of care identifier.</returns>
    Task<List<Admission>> FindByPointOfCareId(ObjectId pocId);
    /// <summary>
    /// Asynchronously retrieves a list of admissions associated with the specified unit identifiers.
    /// </summary>
    /// <param name="unitIds">The list of unit identifiers used to look up the corresponding admissions.</param>
    /// <returns>A task that represents the asynchronous operation, containing the list of admissions matching the provided unit identifiers.</returns>
    Task<List<Admission>> FindByUnitIds(List<ObjectId> unitIds);
    /// <summary>
    /// Asynchronously counts the number of records associated with the specified unit identifier.
    /// </summary>
    /// <param name="unitId">The identifier of the unit used to filter the records.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the count of matching records.</returns>
    Task<long> CountByUnitId(ObjectId unitId);

    /// <summary>
    /// Updates the master list option for the specified units based on the provided options and type, returning the affected admissions.
    /// </summary>
    /// <param name="unitIds">The list of unit identifiers whose master list option should be updated.</param>
    /// <param name="opt">The data transfer object containing the new master list option values to apply.</param>
    /// <param name="typeName">The name of the option type to be updated.</param>
    /// <returns>A task that represents the asynchronous operation, containing the collection of admissions affected by the update.</returns>
    Task<IEnumerable<Admission>> UpdateMasterListOption(List<ObjectId> unitIds, UpdateOptionMasterListDto opt,
            string typeName);

    /// <summary>
    /// Deletes the specified option from the master list for the given units and type, returning the affected admissions.
    /// </summary>
    /// <param name="unitIds">The list of unit identifiers whose master list option should be deleted.</param>
    /// <param name="opt">The option to be removed from the master list.</param>
    /// <param name="typeName">The name of the type associated with the master list option.</param>
    /// <returns>A task that represents the asynchronous operation, containing the collection of <see cref="Admission"/> records affected by the deletion.</returns>
    Task<IEnumerable<Admission>> DeleteMasterListOption(List<ObjectId> unitIds, OptionList opt, string typeName);
    /// <summary>
    /// Asynchronously deletes admissions associated with the specified unit identifier.
    /// </summary>
    /// <param name="unitId">The identifier of the unit whose admissions will be deleted.</param>
    /// <returns>A task that represents the asynchronous operation, containing a value indicating the result of the deletion.</returns>
    Task<bool> DeleteAdmissionsByUnitId(ObjectId unitId);
}