using adas_core.Domain.Models;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.GroupedObservations;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Responses;
using MongoDB.Bson;
using MongoDB.Driver;

namespace adas_core.Application.Services.Interfaces;

public interface IObservationService : IApiRequestService
{
    //REMOVE
    /*
    List<PatientObservation> FindLastObservations(ObjectId patientId, string codingSystem, string code, int num = 2);
    */
    Task<IAsyncCursor<PatientObservation>> FindByPatientIdAsync(ObjectId patientId);

    Task<IAsyncCursor<PatientObservation>> FindByPatientIdAndCodingSystemAsync(ObjectId patientId, string codingSystem,
        string name);

    Task<List<PatientObservation>> FindLastObservations(ObjectId patientId, int num = 2,
        List<string>? filterObservations = null);

    Task UpdateExpiredObservations(List<PatientObservation> expiredObservations);
    Task ExpireObservationsAndRecalculateAsync();
    Task ExpireAlertsAndPowerOffAsync();

    Task<List<PatientObservation>> FindLatestUniqueValuesByName(ObjectId patientId, string name, int? expires);

    Task<List<PatientObservation>> FindLastObservationsByField(ObjectId patientId,
        List<Field>? filterObservations = null, bool mapped = true, CancellationToken ct = default);

    Task<List<PatientObservation?>> FindLastIntravenousLinesObservationByLocation(ObjectId patientId);
    Task InsertObservation(PatientObservation patientObservation, bool persistObs = true, bool mapObs = true);
    Task<bool> InsertIfChanged(string name, PatientObservation observation, bool persistObs = true, bool mapObs = true);
    Task InsertNurseObservation(PatientObservation obs);
    Task DeleteByPatientId(ObjectId id);
    Task Archive(PatientObservation observation);
    Task<PatientObservation?> MapObservation(PatientObservation obs, bool onlyByName = false);
    Task<Dictionary<ObjectId, DateTime>> FindAllLastPatientObservationTime();
    Task<PatientObservation?> MapObservationsByName(PatientObservation obs);
    Task Archive(Patient patient);
    Task ArchiveByPatientId(ObjectId id);

    Task UpdateObservation(PatientObservation observation);
    Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId);

    Task SendObsBroadcast(BasePatientObservation obs);
    Task SendObsBroadcast(List<PatientObservation> obs, PatientLocation location);
    Task SendObsBroadcast(List<PatientObservation> obs, ObjectId pocId);

    Task<PatientObservation?> FindLastBeforeDate(ObjectId patientId, DateTime date, string? obsName);

    Task<List<PatientObservation>?> FindAnyWithSameDate(ObjectId patientId, DateTime date, string? obsName);

    //TODO To implement
    Task<List<PatientObservation>> FindAllBeforeDate(ObjectId patientId, DateTime date,
        List<string>? filterObservations = null);

    //TODO To implement
    Task<List<PatientObservation>> FindAllAfterDate(ObjectId patientId, DateTime date,
        List<string>? filterObservations = null);

    Task<List<PatientObservation>> FindAllBetweenDates(ObjectId patientId, DateTime? startDate, DateTime? endDate,
        List<string>? filterObservations = null, bool fromArchived = false, PaginationFilter? filter = null);

    Task<IEnumerable<PatientObservation>> FindLastNotExpiredObservatonsByPatient(ObjectId patientId, string name,
        int? endAfter = null, int? num = null);


    Task CheckAndExpireObservations();

    IAsyncEnumerable<PatientObservation> FindNotExpiredObservationsShouldBeExpired();


    void ProcessObservations(List<PatientObservation> observations, Patient patient, DateTime messageTime,
        ObservationData? observationData = null);

    Task ExpireObservations();

    Task InsertSimpleObservation(PatientObservation observation);
    Task<PaginationResponse<PatientObservation>> GetPaginatedObservations(PaginationFilter filter);
    Task SaveRequestNurseObsAsync(ApiRequest request);
}