using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.Pumps;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;

namespace adas_core.Application.Customizations.CHUO;

/// <summary>
/// Provides calculated observation data by implementing the <see cref="ICalculatedObservations"/> contract.
/// </summary>
/// <remarks>
/// Instances are constructed with an <see cref="IServiceProvider"/> used to resolve dependencies required by the implementation.
/// </remarks>
public class CalculatedObservations(IServiceProvider serviceProvider) : ICalculatedObservations
{
    private readonly ILogger<CalculatedObservations> _logger =
        serviceProvider.GetRequiredService<ILogger<CalculatedObservations>>();

    /// <summary>
    /// Asynchronously calculates the active bolus for the specified patient.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient for whom the active bolus is being calculated.</param>
    public Task CalculateActiveBolus(ObjectId patientId)
    {
        return Task.CompletedTask;
    }

    /// <summary>
    /// Asynchronously maps the provided <see cref="PumpObservation"/> instance, returning the same instance as the result.
    /// </summary>
    /// <param name="pumpObservation">The pump observation to map.</param>
    /// <returns>A <see cref="Task{PumpObservation}"/> containing the provided pump observation.</returns>
    public async Task<PumpObservation> Map(PumpObservation pumpObservation)
    {
        return await Task.FromResult(pumpObservation);
    }

    /// <summary>
    /// Calculates medicine observations for the specified patient based on the provided active medicines.
    /// </summary>
    /// <param name="activeMedicines">The list of medicines currently active for the patient.</param>
    /// <param name="patientId">The identifier of the patient for whom the observation is calculated.</param>
    public Task CalculateMedicineObservation(List<Medicine> activeMedicines, ObjectId patientId)
    {
        return Task.CompletedTask;

    }

    /// <summary>
    /// Resolves time inconsistencies between a new patient observation and the most recent one, returning a corrected observation when a discrepancy is detected.
    /// </summary>
    /// <param name="newObservation">The new patient observation to compare and reconcile against the last stored observation.</param>
    /// <returns>A task that yields the corrected <see cref="PatientObservation"/>, or <c>null</c> when no time inconsistency is found.</returns>
    /// <exception cref="NotImplementedException">Thrown because the method has not been implemented yet.</exception>
    public Task<PatientObservation?> FixTimeInconsistencyWithLast(PatientObservation newObservation)
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// Retrieves the active treatment records associated with the specified patient.
    /// </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. The task result contains a collection of nullable <see cref="PatientTreatment"/> objects representing the patient's active treatments.</returns>
    /// <exception cref="NotImplementedException">Thrown to indicate that the method has not yet been implemented.</exception>
    public Task<IEnumerable<PatientTreatment?>> GetActiveTreatmentsByPatient(ObjectId id)
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// Maps a patient observation by returning it as-is, logging the operation as a trace entry.
    /// </summary>
    /// <param name="obs">The patient observation to map.</param>
    /// <param name="onlyByName">Indicates whether mapping should be performed by name only.</param>
    /// <returns>A task containing the provided observation.</returns>
    public Task<T?> Map<T>(T obs, bool onlyByName = false) where T : BasePatientObservation
    {
        _logger.LogTrace("Mapping {name} observation {obs}", obs.Name, obs);

        return Task.FromResult<T?>(obs);
    }


    /// <summary>
    /// Maps the specified <see cref="PatientTreatment"/> to a resulting <see cref="PatientTreatment"/> instance asynchronously.
    /// </summary>
    /// <param name="treatment">The patient treatment to be mapped.</param>
    /// <returns>A task that represents the asynchronous mapping operation, containing the resulting <see cref="PatientTreatment"/>.</returns>
    /// <exception cref="NotImplementedException">Thrown when the method is invoked, as the mapping has not been implemented.</exception>
    public Task<PatientTreatment> Map(PatientTreatment treatment)
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// Maps a <see cref="PatientDiagnosis"/> instance to a <see cref="PatientDiagnosis"/> result.
    /// </summary>
    /// <param name="diagnosis">The patient diagnosis to be mapped.</param>
    /// <returns>A task representing the asynchronous operation, containing the mapped <see cref="PatientDiagnosis"/>.</returns>
    /// <exception cref="NotImplementedException">Thrown because the mapping logic has not yet been implemented.</exception>
    public Task<PatientDiagnosis> Map(PatientDiagnosis diagnosis)
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// Performs a pre-mapping step on a list of patient observations before they are inserted.
    /// Currently acts as a pass-through, returning the provided list unchanged as a completed task, but can be overridden to apply transformations or validations.
    /// </summary>
    /// <param name="listToInsert">The list of patient observations to be pre-mapped prior to insertion.</param>
    /// <returns>A completed task containing the provided list of patient observations.</returns>
    public Task<List<PatientObservation>> PreMapList(List<PatientObservation> listToInsert)
    {
        return Task.FromResult(listToInsert);
    }

    /// <summary>
    /// Maps a source alarm onto a <see cref="PatientObservation"/>, returning the observation as-is without applying the alarm's changes.
    /// </summary>
    /// <param name="obs">The existing patient observation to be returned.</param>
    /// <param name="alarmToInsert">The alarm to be associated with the observation (currently not applied).</param>
    /// <returns>A completed <see cref="Task{PatientObservation}"/> containing the original observation.</returns>
    public Task<PatientObservation> MapSourceAlarm(PatientObservation obs, PatientObservationAlarm alarmToInsert)
    {
        return Task.FromResult(obs);
    }

    /// <summary>
    /// Sends an alarm notification for the specified patient observation, identified by the given name and optional alarm code.
    /// </summary>
    /// <param name="obs">The patient observation that triggers the alarm.</param>
    /// <param name="name">The name of the alarm to send.</param>
    /// <param name="code">The optional alarm code providing additional classification for the alarm.</param>
    public Task SendAlarm(PatientObservation obs, string name, AlarmEnum.Name? code)
    {
        return Task.CompletedTask;

    }

    //public Task<List<PatientObservation>> MapList(List<PatientObservation> obsToInsert)
    //{
    //    throw new NotImplementedException();
    //}
}