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

namespace adas_core.Application.Repositories.Interfaces;

public interface ITreatmentRepository : IMongoRepository<PatientTreatment>
{
    /// <summary>
    /// Retrieves the collection of <see cref="PatientTreatment"/> records 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. The task result contains an <see cref="IEnumerable{PatientTreatment}"/> of treatments for the patient; the collection is empty if no treatments are found.</returns>
    Task<IEnumerable<PatientTreatment>> GetByPatientId(ObjectId patientId);
    /// <summary>
    /// Asynchronously retrieves a patient treatment record from the data store that matches the specified identifier.
    /// Returns a cursor over the matching <see cref="PatientTreatment"/> document, or an empty cursor if no record is found.
    /// </summary>
    /// <param name="id">The unique <see cref="ObjectId"/> of the patient treatment record to retrieve.</param>
    /// <returns>A <see cref="Task{IAsyncCursor{PatientTreatment}}"/> that yields a cursor containing the matching patient treatment, if any.</returns>
    Task<IAsyncCursor<PatientTreatment>> GetById(ObjectId id);
    /// <summary>
    /// Asynchronously inserts a new <see cref="PatientTreatment"/> record into the data store.
    /// </summary>
    /// <param name="treatment">The patient treatment entity to be persisted.</param>
    /// <returns>A <see cref="Task"/> that represents the asynchronous insert operation.</returns>
    new Task InsertOneAsync(PatientTreatment treatment);
    /// <summary>
    /// Asynchronously deletes the entity identified by the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the entity to delete.</param>
    new Task DeleteAsync(ObjectId id);
    /// <summary>
    /// Updates an existing <see cref="PatientTreatment"/> record in the data store asynchronously.
    /// </summary>
    /// <param name="treatment">The <see cref="PatientTreatment"/> entity containing the updated information.</param>
    /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous update operation. The task result contains <c>true</c> if the update was successful; otherwise, <c>false</c>.</returns>
    Task<bool> Update(PatientTreatment treatment);
    /// <summary>
    /// Asynchronously retrieves the collection of <see cref="PatientTreatment"/> records associated with the specified patient identifier, returning the results as a cursor for streaming access.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose treatments are being queried.</param>
    /// <returns>A task that yields an <see cref="IAsyncCursor{TDocument}"/> of <see cref="PatientTreatment"/> records matching the given patient identifier.</returns>
    Task<IAsyncCursor<PatientTreatment>> FindByPatientIdAsync(ObjectId patientId);
    /// <summary>
    /// Asynchronously retrieves the collection of 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 an enumerable collection of <see cref="PatientTreatment"/> records for the given patient.</returns>
    Task<IEnumerable<PatientTreatment>> FindByPatientId(ObjectId patientId);

    /// <summary>
    /// Asynchronously deletes a record associated with the specified patient identifier.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose record should be deleted.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the record was successfully deleted; otherwise, <c>false</c>.</returns>
    Task<bool> DeleteByPatientId(ObjectId patientId);
    /// <summary>
    /// Asynchronously 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 queried.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of <see cref="PatientTreatment"/> entries representing the patient's bolus treatments.</returns>
    Task<List<PatientTreatment>> FindBolusTreatments(ObjectId patientId);
    /// <summary>
    /// Updates many records that reference a specific ObjectId, replacing the existing ObjectId with a new one.
    /// Typically used to remap references from <paramref name="oldId"/> to <paramref name="id"/> for the field identified by <paramref name="nameId"/>.
    /// </summary>
    /// <param name="nameId">The name of the field/property that contains the ObjectId reference to be updated.</param>
    /// <param name="id">The new ObjectId value that will replace the existing reference.</param>
    /// <param name="oldId">The current ObjectId value to match and be replaced.</param>
    Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId);
    /// <summary>
    /// Retrieves a paginated, fluent queryable collection of patient treatments based on the provided pagination filter.
    /// </summary>
    /// <param name="filter">The pagination filter containing page size, page number, and other pagination criteria.</param>
    /// <returns>An <see cref="IFindFluent{TSource, TDocument}"/> for <see cref="PatientTreatment"/> that supports further fluent query composition and pagination.</returns>
    IFindFluent<PatientTreatment, PatientTreatment> GetPaginatedTreatments(PaginationFilter filter);
    /// <summary>
    /// Asynchronously retrieves a list of active patient treatments for the specified patient, ordered according to the provided ordering criterion.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose active treatments are to be retrieved.</param>
    /// <param name="order">The ordering criterion applied to the returned list of treatments.</param>
    /// <returns>A task that represents the asynchronous operation, containing a list of active <see cref="PatientTreatment"/> objects for the specified patient.</returns>
    Task<List<PatientTreatment>> GetActiveTreatmentsByPatientIdAndOrder(ObjectId patientId, string order);
}