using adas_core.Application.Subscriptions;
using adas_core.Domain.Models;
using adas_core.Domain.Models.GroupedObservations;
using MongoDB.Bson;

namespace adas_core.Application.Services.Interfaces;

public interface IGroupedObservationService
{
    /// <summary>
    /// Generates a grouped observation for the specified identifier and grouped field, applying the provided time zone for time-based calculations.
    /// </summary>
    /// <param name="id">The unique identifier of the source entity used to produce the grouped observation.</param>
    /// <param name="groupedField">The field definition that determines how the observation is grouped.</param>
    /// <param name="timeZoneId">The identifier of the time zone to apply when interpreting time values. Defaults to "Romance Standard Time".</param>
    /// <param name="cacheIsChecked">Indicates whether the cache should be consulted before generating the result. Defaults to <c>false</c>.</param>
    /// <param name="ct">The cancellation token used to cancel the operation.</param>
    /// <returns>A task that represents the asynchronous generation, producing the resulting <see cref="GroupedObservation"/>.</returns>
    Task<GroupedObservation> GenerateGroupedObservation(ObjectId id, GroupedField groupedField,
            string timeZoneId = "Romance Standard Time", bool cacheIsChecked = false, CancellationToken ct = default);

    /// <summary>
    /// Generates a <see cref="GroupedObservation"/> for the specified patient based on the provided patient observation,
    /// grouped field configuration, and any previously recorded grouped observations, applying the supplied time zone for
    /// date and time handling.
    /// </summary>
    /// <param name="obsPatientId">The identifier of the patient whose observation is being grouped.</param>
    /// <param name="groupedField">The grouped field definition that drives how the observation is categorized and aggregated.</param>
    /// <param name="wsgLastGroupedObservationObs">The list of the most recent grouped observation entries used as context when building the new grouped observation.</param>
    /// <param name="obs">The patient observation to be processed and grouped.</param>
    /// <param name="timeZoneId">The time zone identifier used when computing date and time values for the grouped observation. Defaults to "Romance Standard Time".</param>
    /// <returns>A <see cref="Task{GroupedObservation}"/> that resolves to the generated grouped observation for the patient.</returns>
    Task<GroupedObservation> GenerateGroupedObservation(ObjectId obsPatientId, GroupedField groupedField,
            List<GroupedObservation.GroupedObservationObs> wsgLastGroupedObservationObs, PatientObservation obs,
            string timeZoneId = "Romance Standard Time");

    /// <summary>
    /// Retrieves the most recent observations for a specified patient, optionally filtered by observation types.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose observations are being retrieved.</param>
    /// <param name="num">The maximum number of recent observations to return. Defaults to 2.</param>
    /// <param name="filterObservations">An optional list of observation names to include; if null, all observation types are considered.</param>
    /// <returns>A task that resolves to a list of the most recent <see cref="PatientObservation"/> entries for the patient.</returns>
    Task<List<PatientObservation>> FindLastObservations(ObjectId patientId, int num = 2,
            List<string>? filterObservations = null);

    /// <summary>
    /// Asynchronously creates a new empty observation for the next available slot in the grouped web service subscription.
    /// </summary>
    /// <param name="ws">The grouped web service subscriber for which the next empty observation is created.</param>
    /// <returns>A task that represents the asynchronous operation, containing the newly created <see cref="GroupedObservation"/>.</returns>
    Task<GroupedObservation> CreateNextEmptyObs(WsSubscriberGrouped ws);
    /*
     *
    List<BsonDocument> CalculateShiftObservations(List<BsonDocument> shiftGroupObservations, GroupedField groupedField);
    List<BsonDocument> GenerateShiftObservations(List<BsonDocument> result, GroupedField groupedField);
     */
}