using adas_core.Domain.Models;
using adas_core.Domain.Models.Pumps;
using MongoDB.Bson;

namespace adas_core.Application.Services.Interfaces;

public interface ICalculatedObservationsService
{
    /// <summary>
    /// Maps a <see cref="PatientObservation"/> to a corresponding <see cref="PatientObservation"/>, typically resolved through a lookup or translation process.
    /// </summary>
    /// <param name="obs">The source <see cref="PatientObservation"/> to be mapped.</param>
    /// <param name="onlyByName">When <c>true</c>, restricts the mapping to be performed by name only; otherwise, additional criteria are used.</param>
    /// <returns>A <see cref="Task{PatientObservation}"/> that resolves to the mapped <see cref="PatientObservation"/>, or <c>null</c> if no match is found.</returns>
    Task<PatientObservation?> Map(PatientObservation obs, bool onlyByName = false);
    /// <summary>
    /// Asynchronously maps a <see cref="PatientObservationAlarm"/> instance, optionally performing the mapping
    /// by name only when <paramref name="onlyByName"/> is <c>true</c>. Returns <c>null</c> when no matching
    /// alarm can be resolved based on the selected lookup strategy.
    /// </summary>
    /// <param name="obs">The source patient observation alarm to map.</param>
    /// <param name="onlyByName">When <c>true</c>, restricts the mapping to match by name only; otherwise the
    /// full mapping logic is applied. Defaults to <c>false</c>.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the mapped
    /// <see cref="PatientObservationAlarm"/>, or <c>null</c> if no mapping is found.</returns>
    Task<PatientObservationAlarm?> Map(PatientObservationAlarm obs, bool onlyByName = false);
    /// <summary>
    /// Maps a <see cref="PatientTreatment"/> instance to a projected <see cref="PatientTreatment"/> representation asynchronously.
    /// </summary>
    /// <param name="treatment">The source <see cref="PatientTreatment"/> to be mapped.</param>
    /// <returns>A <see cref="Task{PatientTreatment}"/> that represents the asynchronous mapping operation. The result is the mapped <see cref="PatientTreatment"/>, or <see langword="null"/> if no mapping could be produced.</returns>
    Task<PatientTreatment?> Map(PatientTreatment treatment);
    /// <summary>
    /// Maps the provided <see cref="PumpObservation"/> to a <see cref="PumpObservation"/> result, returning <see langword="null"/> when no mapping is produced.
    /// </summary>
    /// <param name="obs">The source <see cref="PumpObservation"/> to be mapped.</param>
    /// <returns>A <see cref="Task{TResult}"/> containing the mapped <see cref="PumpObservation"/>, or <see langword="null"/> if the mapping yields no result.</returns>
    Task<PumpObservation?> Map(PumpObservation obs);
    /// <summary>
    /// Asynchronously maps the specified <see cref="PatientRecordingAlert"/> to a resulting <see cref="PatientRecordingAlert"/>, returning <see langword="null"/> when no mapping is produced.
    /// </summary>
    /// <param name="obs">The source <see cref="PatientRecordingAlert"/> instance to map.</param>
    /// <returns>A <see cref="Task{TResult}"/> that contains the mapped <see cref="PatientRecordingAlert"/>, or <see langword="null"/> if the source cannot be mapped.</returns>
    Task<PatientRecordingAlert?> Map(PatientRecordingAlert obs);
    /// <summary>
    /// Maps a <see cref="PatientDiagnosis"/> instance to its corresponding representation, returning <see langword="null"/> when no mapping is available.
    /// </summary>
    /// <param name="obs">The source <see cref="PatientDiagnosis"/> to map.</param>
    /// <returns>A <see cref="Task{T}"/> containing the mapped <see cref="PatientDiagnosis"/>, or <see langword="null"/> if the source cannot be mapped.</returns>
    Task<PatientDiagnosis?> Map(PatientDiagnosis obs);
    /// <summary>
    /// Maps a list of patient observations for insertion, returning the transformed list asynchronously.
    /// </summary>
    /// <param name="listToInsert">The list of patient observations to be mapped for insertion.</param>
    /// <returns>A task representing the asynchronous operation, containing the mapped list of patient observations.</returns>
    Task<List<PatientObservation>> MapList(List<PatientObservation> listToInsert);
    /// <summary>
    /// Asynchronously calculates the bolus dose of opiates for the specified patient.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient for whom the bolus opiates calculation is performed.</param>
    Task CalculateBolusOpiates(ObjectId patientId);
    /// <summary>
    /// Asynchronously calculates medicine observations for a patient based on their active medicines.
    /// </summary>
    /// <param name="activeMedicines">The list of medicines currently active for the patient.</param>
    /// <param name="patientId">The unique identifier of the patient.</param>
    /// <returns>A task that represents the asynchronous calculation operation.</returns>
    Task CalculateMedicineObservation(List<Medicine> activeMedicines, ObjectId patientId);
    /// <summary>
    /// Retrieves the active patient treatments associated with the specified patient identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the patient whose active treatments are being requested.</param>
    /// <returns>A task that represents the asynchronous operation, containing an enumerable collection of active PatientTreatment entries for the patient.</returns>
    Task<IEnumerable<PatientTreatment?>> GetActiveTreatmentsByPatient(ObjectId id);
    /// <summary>
    /// Maps a source alarm from a <see cref="PatientObservationAlarm"/> onto a <see cref="PatientObservation"/>, producing an observation enriched with the corresponding alarm information.
    /// </summary>
    /// <param name="observation">The patient observation that serves as the base for the mapping.</param>
    /// <param name="observationAlarm">The source alarm whose data is mapped onto the observation.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the <see cref="PatientObservation"/> populated with the mapped alarm data.</returns>
    Task<PatientObservation> MapSourceAlarm(PatientObservation observation, PatientObservationAlarm observationAlarm);
}