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

namespace adas_core.Application.Services.Interfaces;

public interface IPumpService: IApiRequestService
{
    // Insert manual 
    /// <summary>
    /// Asynchronously inserts a pump observation record into the underlying data store.
    /// </summary>
    /// <param name="obs">The pump observation to persist.</param>
    Task InsertPumpObservation(PumpObservation obs);

    // Mapping
    /// <summary>
    /// Asynchronously maps the specified pump observation to a resulting <see cref="PumpObservation"/>, returning <c>null</c> when no mapping result is produced.
    /// </summary>
    /// <param name="obs">The source pump observation to be mapped.</param>
    /// <returns>A task that represents the asynchronous mapping operation, containing the resulting <see cref="PumpObservation"/> or <c>null</c> if no result is available.</returns>
    Task<PumpObservation?> MapPumpObservation(PumpObservation obs);

    // Consultas por paciente 
    /// <summary>
    /// Retrieves the most recent pump observations for the specified patient.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose pump observations are being queried.</param>
    /// <param name="num">The maximum number of recent observations to return. Defaults to 1.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains a list of the most recent pump observations for the patient, up to the specified count.</returns>
    Task<List<PumpObservation>> FindLastPumpObservations(ObjectId patientId, int num = 1);
    /// <summary>
    /// Asynchronously retrieves the most recent observation timestamp for every patient, returning a dictionary keyed by patient identifier.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation. The task result contains a dictionary mapping each patient's <see cref="ObjectId"/> to their last observation <see cref="DateTime"/>.</returns>
    Task<Dictionary<ObjectId, DateTime>> FindAllLastPatientObservationTime();

    // Gestión de configuración
    /// <summary>
    /// Retrieves the list of configuration pump items associated with the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier used to look up the configuration pump items.</param>
    /// <returns>A task that resolves to a list of <see cref="ConfigPumpItem"/> objects matching the given identifier, or <c>null</c> when no items are found.</returns>
    Task<List<ConfigPumpItem>?> GetItemsById(string id);
    /// <summary>
    /// Asynchronously retrieves the full list of pump configurations from the underlying data source.
    /// </summary>
    /// <returns>A task that resolves to a <see cref="List{ConfigPumps}"/> containing all pump configurations, or <c>null</c> if no configurations are available.</returns>
    Task<List<ConfigPumps>?> GetAllPumpConfig();
    /// <summary>
    /// Asynchronously retrieves the pump configuration associated with the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the pump configuration to retrieve.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the <see cref="ConfigPumps"/> instance matching the specified identifier, or <see langword="null"/> if no configuration is found.</returns>
    Task<ConfigPumps?> GetPumpConfigsById(string id);
    /// <summary>
    /// Asynchronously updates the pump configuration.
    /// </summary>
    /// <param name="config">The pump configuration to update.</param>
    /// <returns>A task that represents the asynchronous operation, containing the updated <see cref="ConfigPumps"/> or null if not found.</returns>
    Task<ConfigPumps?> UpdatePumpConfig(ConfigPumps config);
    /// <summary>
    /// Inserts a new pump configuration into the system asynchronously.
    /// </summary>
    /// <param name="config">The pump configuration to be inserted.</param>
    /// <returns>A task that represents the asynchronous operation, containing the inserted <see cref="ConfigPumps"/> or <c>null</c> if the insertion fails.</returns>
    Task<ConfigPumps?> InsertPumpConfig(ConfigPumps config);
    /// <summary>
    /// Deletes the specified pump configuration.
    /// </summary>
    /// <param name="config">The pump configuration to delete.</param>
    /// <returns>A task that represents the asynchronous delete operation. The task result is <c>true</c> if the configuration was deleted successfully; otherwise, <c>false</c>.</returns>
    Task<bool> DeletePumpConfig(ConfigPumps config);

    // Paginación 
    /// <summary>
    /// Retrieves a paginated collection of pump observations based on the provided filter criteria.
    /// Returns null when no pump observations match the supplied pagination filter.
    /// </summary>
    /// <param name="filter">The pagination filter that defines page size, page number, and any additional filtering criteria applied to the pump observations.</param>
    /// <returns>A task that resolves to a <see cref="PaginationResponse{PumpObservation}"/> containing the matching pump observations, or null when no results are found.</returns>
    Task<PaginationResponse<PumpObservation>?> GetPaginatedPump(PaginationFilter filter);

    // Archivado / limpieza
    /// <summary>
    /// Asynchronously deletes records associated with the specified patient identifier.
    /// </summary>
    /// <param name="id">The ObjectId of the patient whose related records should be deleted.</param>
    Task DeleteByPatientId(ObjectId id);
    /// <summary>
    /// Archives the specified patient, marking the patient record as archived in the system.
    /// </summary>
    /// <param name="patient">The patient to be archived.</param>
    Task Archive(Patient patient);
    /// <summary>
    /// Asynchronously archives the data associated with the specified patient identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the patient whose data should be archived.</param>
    /// <returns>A task that represents the asynchronous archive operation.</returns>
    Task ArchiveByPatientId(ObjectId id);

    // Mantenimiento ids
    /// <summary>
    /// Asynchronously updates multiple records, replacing the specified old ObjectId with a new one in the field identified by <paramref name="nameId"/>.
    /// </summary>
    /// <param name="nameId">The name of the field whose ObjectId value should be updated.</param>
    /// <param name="id">The new ObjectId value to assign.</param>
    /// <param name="oldId">The existing ObjectId value to be replaced.</param>
    Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId);
}