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

namespace adas_core.Application.Services.Interfaces;

public interface ITreatmentService : IApiRequestService
{
    /// <summary>
    /// Inserts a new <see cref="PatientTreatment"/> record into the underlying data store.
    /// </summary>
    /// <param name="treatment">The patient treatment entity to be added.</param>
    Task Insert(PatientTreatment treatment);
    /// <summary>
    /// Asynchronously deletes an entity associated with the specified patient identifier.
    /// </summary>
    /// <param name="id">The <see cref="ObjectId"/> representing the unique identifier of the patient whose related entity should be removed.</param>
    /// <returns>A <see cref="Task{TResult}"/> containing <c>true</c> if the deletion was successful; otherwise, <c>false</c>.</returns>
    Task<bool> DeleteByPatientId(ObjectId id);
    /// <summary>
    /// Asynchronously deletes the entity identified by the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the entity to delete.</param>
    Task DeleteById(ObjectId id);
    /// <summary>
    /// Archives records associated with the specified patient identifier.
    /// </summary>
    /// <param name="id">The ObjectId of the patient whose records should be archived.</param>
    Task ArchiveByPatientId(ObjectId id);
    /// <summary>
    /// Archives the specified patient, marking them as archived in the system.
    /// </summary>
    /// <param name="patient">The patient to archive.</param>
    Task Archive(Patient patient);
    /// <summary>
    /// Updates an existing patient treatment record in the system.
    /// </summary>
    /// <param name="patientTreatment">The patient treatment entity containing the updated information to be persisted.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains <c>true</c> if the treatment was updated successfully; otherwise, <c>false</c>.</returns>
    Task<bool> UpdateTreatment(PatientTreatment patientTreatment);
    /// <summary>
    /// Updates many records by replacing the specified old ObjectId with the new ObjectId in the field identified by nameId.
    /// </summary>
    /// <param name="nameId">The name of the field that contains the ObjectId to be updated.</param>
    /// <param name="id">The new ObjectId value that will replace the existing one.</param>
    /// <param name="oldId">The existing ObjectId value to be replaced.</param>
    Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId);
    /// <summary>
    /// Retrieves all treatments associated with the specified patient identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the patient whose treatments are to be retrieved.</param>
    /// <returns>A task that represents the asynchronous operation, containing a collection of PatientTreatment objects for the specified patient.</returns>
    Task<IEnumerable<PatientTreatment>> GetTreatmentsByPatientId(ObjectId id);
    /// <summary>
    /// Retrieves the active treatment records associated with the specified patient identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the patient whose active treatments should be retrieved.</param>
    /// <returns>A task that represents the asynchronous operation, containing an enumerable collection of active <see cref="PatientTreatment"/> records, which may include null entries.</returns>
    Task<IEnumerable<PatientTreatment?>> GetActiveTreatmentsByPatient(ObjectId id);
    /// <summary>
    /// Asynchronously retrieves a cursor over the <see cref="PatientTreatment"/> records associated with the specified patient identifier.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose treatments should be returned.</param>
    /// <returns>A <see cref="Task{TResult}"/> yielding an <see cref="IAsyncCursor{TDocument}"/> that iterates the matching <see cref="PatientTreatment"/> documents.</returns>
    Task<IAsyncCursor<PatientTreatment>> FindByPatientIdAsync(ObjectId patientId);
    /// <summary>
    /// Asynchronously retrieves all patient treatments associated with the specified patient identifier.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose treatments are being queried.</param>
    /// <returns>A task that represents the asynchronous operation, containing a collection of <see cref="PatientTreatment"/> instances for the specified patient.</returns>
    Task<IEnumerable<PatientTreatment>> FindByPatientId(ObjectId patientId);
    /// <summary>
    /// Retrieves the list of bolus treatments associated with the specified patient.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose bolus treatments are being retrieved.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of <see cref="PatientTreatment"/> records representing the patient's bolus treatments.</returns>
    Task<List<PatientTreatment>> GetBolusTreatments(ObjectId patientId);
    /// <summary>
    /// Retrieves a paginated list of patient treatments based on the specified filter criteria.
    /// </summary>
    /// <param name="filter">The pagination filter used to control the page number, page size, and other query options.</param>
    /// <returns>A task that represents the asynchronous operation, containing the paginated patient treatment results.</returns>
    Task<PaginationResponse<PatientTreatment>> GetPaginatedTreatments(PaginationFilter filter);
    /// <summary>
    /// Retrieves the list of active treatments associated with the specified patient, sorted according to the provided order parameter.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose active treatments are being queried.</param>
    /// <param name="order">A string defining the ordering criteria applied to the returned treatments.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of active <see cref="PatientTreatment"/> entries for the patient.</returns>
    Task<List<PatientTreatment>> GetActiveTreatmentsByPatientIdAndOrder(ObjectId patientId, string order);
}