using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.DTO;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.Masters;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Responses;
using MongoDB.Bson;

namespace adas_core.Application.Services.Interfaces;

public interface IPatientService : IApiRequestService
{
    Task<Patient?> FindByPatientId(string patientId, bool withLocation = false);
    Task<Patient?> FindByPatientIdWithLocale(string patientId, LocaleEnum localeEnum);
    Task<Patient?> FindByPatientNumberArchived(string patientNumber);
    Task<Patient?> FindByPatientNumber(string patientNumber, bool withLocation = false);
    Task<Patient?> FindByLocation(PatientLocation? location);
    Task<Patient?> FindByPointOfCareId(ObjectId pocId);
    Task<Patient?> FindByUnitAndPocId(ObjectId unit, ObjectId pointOfCare);
    Task<List<Patient>> FindByPointOfCare(string pointOfCare);
    Task<long> CountPatientsByUnitId(ObjectId unitId);

    Task<Patient?> FindPatient(string? patientId, string? patientNumber, PatientLocation? location,
        bool findByLocation = false);

    Task Insert(Patient patient);
    Task InsertAsync(Patient patient);
    Task ArchivePatient(Patient patient);
    Task ArchivePatientData(ObjectId patientid);
    Task MergePatient(Patient patient, string oldPatienNumber);
    Task UpdateLocation(ObjectId id, PatientLocation? location);
    Task UpdateAttendingDoctor(ObjectId id, Person doctor);
    Task UpdatePatientData(ObjectId id, string patientNumber, Person data, bool updatePatientNumber = true);
    Task UpdatePatientData(ObjectId id, string patientNumber, Patient patient, bool updatePatientNumber = true);
    Task Update(Patient patient);
    Task<bool> Move(Patient patient, ObjectId newPocId, ObjectId oldPocId);
    Task<Patient?> FindById(ObjectId id, bool withLocation = false);
    Task<Box?> GetBox(PointOfCare poc, bool observations = false, List<string>? filterObservations = null);
    Task<Patient?> CreatePatientFromRequest(ApiRequest apiRequest, bool ignoreLocation = false);
    Task<Patient?> FindPatientByApiRequest(ApiRequest apiRequest);
    Task ArchivePatientWithoutObservationsSinceDate(DateTime date);

    Task ArchiveDischargedPatients(int hoursBeforeArchive);
    Task<List<Patient>> FindAll(bool withLocation = false);
    Task<PaginationResponse<Patient>> GetPaginatedPatients(PaginationFilter filter);

    Task DischargeInactivePatients(DateTime sinceDate, int hoursBeforeArchive);
    Task<Patient?> UpdateOne(Patient updatedPatient);

    Task SendNewPatientBroadcast(Patient patient);
    Task SendPatientUpdateBroadcast(Patient patient);
    Task<List<Patient>> FindInActivePoC();
    Task<List<Patient>> FindInInactivePoC();

    Task<Patient?> GetByPointOfCare(PointOfCare item, bool observations = false,
        List<string>? filterObservations = null);

    Task<Patient?> GetByPointOfCareAndLocale(PointOfCare item, Unit? unit, LocaleEnum? localeEnum);
    Task<Patient?> UpdatePatientAltable(ObjectId patientId, OptionList altable, User? user);
    Task ExitPatientById(ObjectId id, bool archivePatient = true);

    Task<Patient?> UpdatePatientMasterList(ObjectId patientId, MasterListType typeName,
        List<OptionList> updatedOptions,
        User? user, List<OptionList>? carePlanLog);

    Task GenerateNurseCarePlanAndInsert(MasterListType carePlanType, List<OptionList>? options,
        Patient patient, User? user);

    Task UpdatePatientIncomingData(ObjectId patientId, Patient person);
    Task UpdatePatientDemographicData(ObjectId patientId, Patient person, User? user);
    Task<Patient?> SearchByPatientNumberAndDistinctUnit(string patientNumber, ObjectId unitId);
    Task<List<Patient>> FindAllPatientWithFinishedProcedures(int archiveProcedureEndDateAfterMinutes);
    Task<List<Patient>> FindAllPatientWithFinishedTest(int archiveTestEndDateAfterMinutes);
    Task<List<Patient>> FindAllPatientWithFinishedTreatment(int archiveTreatmentEndDateAfterMinutes);

    Task UpdatePatientIncomingData(ObjectId patientId, Patient person, PatientIncomeData personDataChange,
        User user);

    Task UpdatePatientMasterListItemChange(UpdateOptionMasterListDto opt, IEnumerable<Unit> unitList,
        string typeName);

    Task DeletePatientMasterListItem(OptionList opt, IEnumerable<Unit> unitList, string typeName);
}