using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.GroupedObservations;
using adas_core.Domain.Models.MongoModels;
using MongoDB.Bson;

namespace adas_core.Application.Services.Interfaces;

public interface IAlarmService : IApiRequestService
{
    /// <summary>
    /// Retrieves the most recent patient observations for the specified patient, optionally filtered by a set of fields.
    /// </summary>
    /// <param name="patientId">The identifier of the patient whose last observations should be retrieved.</param>
    /// <param name="filterObservations">An optional list of fields to restrict the returned observations; when null, no field filter is applied.</param>
    /// <returns>A task that resolves to the list of the patient's most recent <see cref="PatientObservationAlarm"/> records.</returns>
    public Task<List<PatientObservationAlarm>> FindLastObservationsByField(ObjectId patientId,
            List<Field>? filterObservations = null);

    /// <summary>
    /// Retrieves the most recent non-expired patient observation alarms for a specific patient, based on the provided alarm fields and configuration.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose alarms are being queried.</param>
    /// <param name="dataAlarmfields">The list of fields used to identify and filter the patient observation alarm data.</param>
    /// <param name="configAlarm">The list of configuration observations that define the alarm criteria, including expiration rules.</param>
    /// <returns>A task that represents the asynchronous operation, containing the list of the latest non-expired <see cref="PatientObservationAlarm"/> entries for the patient.</returns>
    Task<List<PatientObservationAlarm>> FindLastValuesNotExpired(ObjectId patientId, List<Field> dataAlarmfields,
            List<ConfigObservation> configAlarm);

    /// <summary>
    /// Maps a patient observation alarm, optionally restricting the lookup to name-based matching only. Returns a null result when no matching alarm is found.
    /// </summary>
    /// <param name="obs">The patient observation alarm to be mapped.</param>
    /// <param name="onlyByName">When true, limits the mapping to lookups performed by name only.</param>
    /// <returns>A task that resolves to the mapped patient observation alarm, or null if no corresponding alarm is found.</returns>
    public Task<PatientObservationAlarm?> MapObservation(PatientObservationAlarm obs, bool onlyByName = false);
    /// <summary>
    /// Maps the given patient observation alarm to a corresponding record by name, returning a null result when no matching observation is found.
    /// </summary>
    /// <param name="obs">The patient observation alarm to be mapped by name.</param>
    /// <returns>A task containing the mapped <see cref="PatientObservationAlarm"/>, or <c>null</c> if no matching observation exists.</returns>
    public Task<PatientObservationAlarm?> MapObservationsByName(PatientObservationAlarm obs);

    /// <summary>
    /// Asynchronously calculates an alarm test result based on the provided patient observation value.
    /// </summary>
    /// <param name="source">The base patient observation value used as input for the alarm evaluation.</param>
    /// <param name="name">The name that identifies the alarm test to be calculated.</param>
    Task CalculateAlarmTest(BasePatientObservationValue source, string name);

    /// <summary>
    /// Sends an alarm notification associated with the specified patient observation, using the provided name, optional code, severity, and type.
    /// </summary>
    /// <param name="obs">The patient observation that triggers the alarm.</param>
    /// <param name="name">The display name of the alarm.</param>
    /// <param name="code">The optional alarm code identifier, or null when not applicable.</param>
    /// <param name="severity">The severity level assigned to the alarm.</param>
    /// <param name="type">The type category of the alarm.</param>
    /// <returns>A task that represents the asynchronous alarm sending operation.</returns>
    Task SendAlarm(PatientObservation obs, string name, AlarmEnum.Name? code, AlarmEnum.Severity severity,
            AlarmEnum.Type type);

    /// <summary>
    /// Asynchronously checks the observation alarm for the specified patient observation.
    /// </summary>
    /// <param name="obs4">The patient observation to evaluate for alarm conditions.</param>
    Task CheckObservationAlarm(PatientObservation obs4);

    /// <summary>
    /// Processes a collection of patient observation alarms, associating them with the corresponding observations and patient, and recording the processing time.
    /// </summary>
    /// <param name="alarmObservations">The list of patient observation alarms to be processed.</param>
    /// <param name="observations">The list of patient observations related to the alarms.</param>
    /// <param name="patient">The patient to whom the observations and alarms belong.</param>
    /// <param name="messageTime">The timestamp associated with the message being processed.</param>
    /// <param name="observationData">Optional additional observation data used during processing.</param>
    Task ProcessAlarmObservations(List<PatientObservationAlarm> alarmObservations,
            List<PatientObservation> observations, Patient patient,
            DateTime messageTime, ObservationData? observationData = null);
}