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
{
///
/// Asynchronously retrieves a patient by their unique patient identifier, optionally including location information.
///
/// The unique identifier of the patient to find.
/// When set to true, includes location details in the returned patient; otherwise, only basic patient data is returned.
/// A task that represents the asynchronous operation. The task result contains the found , or null if no patient matches the specified identifier.
Task FindByPatientId(string patientId, bool withLocation = false);
///
/// Asynchronously retrieves a patient by their unique identifier, applying the specified locale for localized data.
///
/// The unique identifier of the patient to locate.
/// The locale to use when retrieving or formatting localized patient information.
/// A task that resolves to the matching patient, or null if no patient is found for the given identifier.
Task FindByPatientIdWithLocale(string patientId, LocaleEnum localeEnum);
///
/// Asynchronously retrieves an archived matching the specified patient number, returning null when no matching archived record is found.
///
/// The unique patient number used to look up the archived patient record.
/// A that yields the matching archived , or null if no archived patient is found.
Task FindByPatientNumberArchived(string patientNumber);
///
/// Retrieves a patient by their unique patient number, optionally including location information in the result.
///
/// The unique patient number used to look up the patient.
/// When true, location information is included in the returned patient; otherwise, it is omitted.
/// A task that yields the matching if one is found, or null when no patient matches the given number.
Task FindByPatientNumber(string patientNumber, bool withLocation = false);
///
/// Asynchronously retrieves a patient associated with the specified location.
/// Returns if no matching patient is found or if the location is .
///
/// The patient location used to search for a matching patient. May be .
/// A that yields the matching , or if no patient is found.
Task FindByLocation(PatientLocation? location);
///
/// Asynchronously retrieves a patient associated with the specified Point of Care identifier.
///
/// The ObjectId representing the Point of Care identifier used to look up the patient.
/// A task that represents the asynchronous operation. The task result contains the matching if found; otherwise, null.
Task FindByPointOfCareId(ObjectId pocId);
///
/// Asynchronously retrieves a patient identified by the specified unit and point-of-care identifiers.
///
/// The unique identifier of the unit to search within.
/// The unique identifier of the point-of-care associated with the patient.
/// A task that yields the matching , or null if no patient is found for the given unit and point-of-care.
Task FindByUnitAndPocId(ObjectId unit, ObjectId pointOfCare);
///
/// Asynchronously retrieves a list of patients associated with the specified point of care.
///
/// The point of care identifier used to locate matching patients.
/// A task that represents the asynchronous operation, containing a list of objects that match the specified point of care.
Task> FindByPointOfCare(string pointOfCare);
///
/// Asynchronously counts the number of patients associated with the specified unit identifier.
///
/// The ObjectId of the unit whose patients should be counted.
/// A task that represents the asynchronous operation, containing the total count of patients for the given unit.
Task CountPatientsByUnitId(ObjectId unitId);
///
/// Asynchronously locates a patient using the provided identifiers, supporting lookup by patient
/// ID, patient number, or location when is enabled.
///
/// The unique identifier of the patient to find.
/// The patient number used as an alternative lookup key.
/// The patient location used when searching by location.
/// When true, the search is performed using the supplied
/// instead of the patient identifiers.
/// A that yields the matching , or
/// null if no patient is found.
Task FindPatient(string? patientId, string? patientNumber, PatientLocation? location,
bool findByLocation = false);
///
/// Asynchronously inserts a new patient record into the data store.
///
/// The patient entity to be inserted.
Task Insert(Patient patient);
///
/// Asynchronously inserts the specified into the data store.
///
/// The patient entity to be persisted.
Task InsertAsync(Patient patient);
///
/// Archives the specified patient record.
///
/// The patient to archive.
Task ArchivePatient(Patient patient);
///
/// Archives the patient data identified by the specified patient identifier.
///
/// The unique identifier of the patient whose data should be archived.
Task ArchivePatientData(ObjectId patientid);
///
/// Merges the specified patient record with the existing patient identified by the old patient number.
///
/// The patient data to merge into the existing record.
/// The identifier of the existing patient record to be merged.
Task MergePatient(Patient patient, string oldPatienNumber);
///
/// Updates the location of a patient identified by the specified object identifier.
///
/// The unique identifier of the patient whose location will be updated.
/// The new patient location, or null if no location is provided.
Task UpdateLocation(ObjectId id, PatientLocation? location);
///
/// Updates the attending doctor for the entity identified by the specified identifier.
///
/// The identifier of the entity whose attending doctor will be updated.
/// The new attending doctor to assign to the entity.
/// A task that represents the asynchronous update operation.
Task UpdateAttendingDoctor(ObjectId id, Person doctor);
///
/// Updates the data of an existing patient identified by the given identifier, optionally replacing the patient number when the flag is true.
///
/// The unique identifier of the patient whose data will be updated.
/// The patient number to be applied to the patient.
/// The person data to assign to the patient.
/// Indicates whether the patient number should also be updated; defaults to true.
Task UpdatePatientData(ObjectId id, string patientNumber, Person data, bool updatePatientNumber = true);
///
/// Updates the patient data for the specified patient identified by and , applying the changes from the provided object. When is true, the patient number is also updated as part of the operation; otherwise, only the remaining patient fields are updated.
///
/// The unique identifier of the patient record to update.
/// The current patient number used to locate the patient record.
/// The patient object containing the updated data to be applied.
/// A flag indicating whether the patient number should also be updated; defaults to true.
/// A that represents the asynchronous update operation.
Task UpdatePatientData(ObjectId id, string patientNumber, Patient patient, bool updatePatientNumber = true);
///
/// Updates the specified patient record.
///
/// The patient whose information will be updated.
Task Update(Patient patient);
///
/// Moves the specified patient from the old point of care to the new point of care.
///
/// The patient to be moved.
/// The identifier of the destination point of care.
/// The identifier of the source point of care.
/// A task that resolves to true if the move was successful; otherwise, false.
Task Move(Patient patient, ObjectId newPocId, ObjectId oldPocId);
///
/// Retrieves a patient by their unique identifier, optionally including location information.
/// Returns null when no patient matches the provided identifier.
///
/// The used to look up the patient.
/// When true, includes the patient's location data in the result; otherwise, location data is omitted.
/// A that resolves to the matching , or null if no patient is found.
Task FindById(ObjectId id, bool withLocation = false);
///
/// Retrieves a associated with the specified , returning when no box is found for the given point of care.
///
/// The point of care used to look up the associated box.
/// When , observations are included with the returned box; otherwise, observations are omitted.
/// An optional list of observation identifiers used to restrict which observations are loaded when is .
/// A that resolves to the matching , or if no box exists for the specified point of care.
Task GetBox(PointOfCare poc, bool observations = false, List? filterObservations = null);
///
/// Creates a instance from the provided , optionally ignoring location information during the creation process.
///
/// The API request containing the data used to construct the patient.
/// When true, location information is ignored during patient creation. Defaults to false.
/// A task that represents the asynchronous operation. The task result contains the created , or null if the patient could not be created.
Task CreatePatientFromRequest(ApiRequest apiRequest, bool ignoreLocation = false);
///
/// Asynchronously finds a patient based on the information provided in the specified API request.
///
/// The API request containing the data used to look up the patient.
/// A task that represents the asynchronous operation. The task result contains the matching if found, or null if no patient matches the request.
Task FindPatientByApiRequest(ApiRequest apiRequest);
///
/// Archives patients who have no observations recorded since the specified date.
///
/// The cutoff date; patients without observations after this date are archived.
Task ArchivePatientWithoutObservationsSinceDate(DateTime date);
///
/// Archives patient records for patients who have been discharged longer than the specified time threshold.
///
/// The number of hours a patient must have been discharged before being archived.
Task ArchiveDischargedPatients(int hoursBeforeArchive);
///
/// Retrieves all patients, optionally including their location data when requested.
///
/// Indicates whether location information should be included in the returned patient records.
/// A task that represents the asynchronous operation, containing a list of objects.
Task> FindAll(bool withLocation = false);
///
/// Retrieves a paginated list of patients based on the provided pagination filter.
///
/// The pagination filter that defines the paging criteria used to retrieve patients.
/// A task that represents the asynchronous operation. The task result contains a with the requested page of patients.
Task> GetPaginatedPatients(PaginationFilter filter);
///
/// Discharges patients who have been inactive since the specified date and archives them after the defined retention period.
///
/// The date used to identify patients that have been inactive since this point in time.
/// The number of hours of inactivity that must elapse before a discharged patient is archived.
Task DischargeInactivePatients(DateTime sinceDate, int hoursBeforeArchive);
///
/// Updates an existing patient record with the provided patient data. Returns the updated patient, or null if no matching patient was found.
///
/// The patient object containing the updated information to be persisted.
/// A that resolves to the updated , or null if the patient could not be found.
Task UpdateOne(Patient updatedPatient);
///
/// Sends an asynchronous broadcast notification to inform relevant subscribers or systems about a newly registered patient.
///
/// The patient whose information will be included in the broadcast notification.
Task SendNewPatientBroadcast(Patient patient);
///
/// Asynchronously sends a broadcast notification about an update to the specified patient.
///
/// The patient whose update information will be broadcast.
Task SendPatientUpdateBroadcast(Patient patient);
///
/// Asynchronously retrieves the list of inactive Patients of Care (PoC), allowing consumers to identify
/// patients that are no longer active in the system for reporting, cleanup, or follow-up workflows.
///
/// A task representing the asynchronous operation, containing a list of inactive records.
Task> FindInActivePoC();
///
/// Retrieves a list of patients associated with inactive PoC records.
///
/// A task that represents the asynchronous operation. The task result contains a list of objects associated with inactive PoC records.
Task> FindInInactivePoC();
///
/// Retrieves a associated with the specified point of care, returning null when no matching patient is found.
/// When is true, the result includes the patient's observations, optionally restricted by the identifiers supplied in .
///
/// The point of care used to look up the associated patient.
/// Indicates whether the patient's observations should be included in the returned patient.
/// An optional list of observation identifiers used to filter which observations are returned when is true.
/// A that resolves to the matching , or null if no patient is found for the given point of care.
Task GetByPointOfCare(PointOfCare item, bool observations = false,
List? filterObservations = null);
///
/// Asynchronously retrieves a matching the specified point of care, optionally narrowed by unit and locale.
///
/// The point of care used to locate the patient.
/// An optional unit that further filters the lookup.
/// An optional locale used to scope the search.
/// A task that yields the matching , or null when no patient is found.
Task GetByPointOfCareAndLocale(PointOfCare item, Unit? unit, LocaleEnum? localeEnum);
///
/// Updates the altable (allergy table) information for the specified patient and returns the updated patient.
///
/// The unique identifier of the patient whose altable is being updated.
/// The option list containing the altable data to apply to the patient.
/// The user performing the update, or null when no user context is available.
/// A task that resolves to the updated , or null if the patient was not found.
Task UpdatePatientAltable(ObjectId patientId, OptionList altable, User? user);
///
/// Exits a patient identified by the given identifier, optionally archiving the patient record.
///
/// The unique identifier of the patient to exit.
/// When true, the patient record is archived as part of the exit process; when false, archiving is skipped.
Task ExitPatientById(ObjectId id, bool archivePatient = true);
///
/// Updates the specified master list for a patient with the provided options and returns the updated patient record.
///
/// The identifier of the patient whose master list is being updated.
/// The type of master list to update.
/// The new list of options to apply to the master list.
/// The user performing the update, or null if not specified.
/// Optional care plan log entries associated with the update.
/// A task that returns the updated , or null if the patient was not found.
Task UpdatePatientMasterList(ObjectId patientId, MasterListType typeName,
List updatedOptions,
User? user, List? carePlanLog);
///
/// Generates a nurse care plan of the specified type, using the provided options, and inserts it for the patient.
///
/// The master list type that determines which nurse care plan template to generate.
/// Optional list of options applied during care plan generation. May be null.
/// The patient for whom the nurse care plan is generated and inserted.
/// The user associated with the care plan generation. May be null.
/// A task that completes when the nurse care plan has been generated and inserted.
Task GenerateNurseCarePlanAndInsert(MasterListType carePlanType, List? options,
Patient patient, User? user);
///
/// Asynchronously updates the incoming data for the specified patient by applying the provided patient information.
///
/// The unique identifier of the patient whose incoming data is being updated.
/// The patient object containing the incoming data to be applied to the patient record.
Task UpdatePatientIncomingData(ObjectId patientId, Patient person);
///
/// Asynchronously updates the demographic data of an existing patient identified by the specified patient identifier.
///
/// The unique identifier of the patient whose demographic data is to be updated.
/// The patient object containing the new demographic information to apply.
/// The user performing the update operation, or if no user context is available.
Task UpdatePatientDemographicData(ObjectId patientId, Patient person, User? user);
///
/// Searches for a patient by their patient number within a distinct unit.
///
/// The patient number used to identify the patient.
/// The identifier of the distinct unit where the patient is registered.
/// A task that represents the asynchronous operation. The task result contains the matching if found; otherwise, .
Task SearchByPatientNumberAndDistinctUnit(string patientNumber, ObjectId unitId);
///
/// Asynchronously retrieves all patients whose procedures have been finished, filtering based on the specified archive threshold for procedure end times.
///
/// The number of minutes after the procedure end date used as the archive threshold to qualify patients with finished procedures.
/// A task that represents the asynchronous operation, containing a list of objects that match the finished procedures criteria.
Task> FindAllPatientWithFinishedProcedures(int archiveProcedureEndDateAfterMinutes);
///
/// Asynchronously retrieves all patients who have completed a test, using the specified archive window in minutes to determine which tests are considered finished.
///
/// The time window in minutes applied to the test end date to identify tests that should be treated as finished/archived.
/// A task that represents the asynchronous operation, containing a list of instances with finished tests.
Task> FindAllPatientWithFinishedTest(int archiveTestEndDateAfterMinutes);
///
/// Retrieves a list of patients whose treatments have finished, based on the specified archive time threshold in minutes after the treatment end date.
///
/// The number of minutes after the treatment end date used to determine which finished treatments should be included.
/// A task representing the asynchronous operation, containing a list of patients with finished treatment matching the specified criteria.
Task> FindAllPatientWithFinishedTreatment(int archiveTreatmentEndDateAfterMinutes);
///
/// Updates the incoming income data of a patient using the specified changes and the user performing the operation.
///
/// The unique identifier of the patient whose income data is being updated.
/// The patient entity associated with the update.
/// The income data changes to apply to the patient.
/// The user performing the update operation.
Task UpdatePatientIncomingData(ObjectId patientId, Patient person, PatientIncomeData personDataChange,
User user);
///
/// Updates a patient master list item change based on the provided update options, unit list, and type name.
///
/// The update options for the master list item.
/// The collection of units associated with the update.
/// The name of the type used to categorize the master list item.
Task UpdatePatientMasterListItemChange(UpdateOptionMasterListDto opt, IEnumerable unitList,
string typeName);
///
/// Deletes a patient master list item based on the specified option, unit list, and type name.
///
/// The option list containing the details of the patient master list item to delete.
/// The collection of units associated with the patient master list item.
/// The name of the type identifying the patient master list item to be deleted.
Task DeletePatientMasterListItem(OptionList opt, IEnumerable unitList, string typeName);
}