using adas_core.Domain.Models;
using adas_core.Domain.Models.DTO;
using adas_core.Domain.Models.MongoModels;
using MongoDB.Bson;

namespace adas_core.Application.Services.Interfaces;

public interface IAdminPanelService
{
    /// <summary>
    /// Asynchronously deletes a unit identified by its unique identifier from the data store.
    /// Returns a result indicating whether the deletion was successful (e.g., true if the unit was found and removed, false otherwise).
    /// </summary>
    /// <param name="unitId">The unique identifier of the unit to delete.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the unit was successfully deleted; otherwise, <c>false</c> if the unit was not found.</returns>
    Task<bool> DeleteUnitById(ObjectId unitId);
    /// <summary>
    /// Inserts a new <see cref="Unit"/> into the data store and returns the inserted entity.
    /// </summary>
    /// <param name="unit">The <see cref="Unit"/> to insert.</param>
    /// <returns>A <see cref="Task{T}"/> that resolves to the inserted <see cref="Unit"/>, or <see langword="null"/> if the insert could not be completed.</returns>
    Task<Unit?> InsertUnit(Unit unit);

    #region Patient

    /// <summary>
    /// Creates a new patient based on the provided admin panel request.
    /// </summary>
    /// <param name="apiRequest">The admin panel request containing the data needed to create the patient.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the created <see cref="Patient"/>, or <c>null</c> if no patient was created.</returns>
    Task<Patient?> CreatePatient(AdmPanelRequest apiRequest);
    /// <summary>
    /// Asynchronously retrieves the patient associated with the specified location.
    /// </summary>
    /// <param name="location">The location used to look up the associated patient.</param>
    /// <returns>A task that resolves to the <see cref="Patient"/> found at the given location, or <c>null</c> if no patient is associated with that location.</returns>
    Task<Patient?> FindPatientByLocation(PatientLocation location);
    /// <summary>
    /// Asynchronously retrieves a <see cref="Patient"/> by their unique patient number.
    /// </summary>
    /// <param name="patientNumber">The unique identifier of the patient to look up.</param>
    /// <returns>A <see cref="Task{TResult}"/> that yields the matching <see cref="Patient"/>, or <c>null</c> if no patient is found with the specified number.</returns>
    Task<Patient?> FindPatientByPatientNumber(string patientNumber);

    /// <summary>
    /// Asynchronously retrieves a patient from the data store using the specified unique identifier.
    /// Returns null when no patient matches the provided identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the patient to retrieve.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the patient if found; otherwise, null.</returns>
    Task<Patient?> FindPatientById(ObjectId id);

    //List<person> FindAllPatient();
    /// <summary>
    /// Asynchronously finds and returns a <see cref="Patient"/> based on the criteria provided in the admission panel request.
    /// Returns <c>null</c> when no matching patient is found.
    /// </summary>
    /// <param name="request">The admission panel request containing the search criteria used to locate the patient.</param>
    /// <returns>A <see cref="Task{TResult}"/> that yields the matching <see cref="Patient"/> if found, or <c>null</c> otherwise.</returns>
    Task<Patient?> FindPatient(AdmPanelRequest request);
    /// <summary>
    /// Asynchronously retrieves the dependency information DTO for the specified <paramref name="unit"/>.
    /// Returns <c>null</c> when no dependency information is available for the unit.
    /// </summary>
    /// <param name="unit">The unit for which to retrieve dependency information.</param>
    /// <returns>A <see cref="Task{UnitInfoDto}"/> that yields the unit dependency DTO, or <c>null</c> if none is found.</returns>
    Task<UnitInfoDto?> GetUnitDependencyDto(Unit unit);

    /// <summary>
    /// Updates the patient location based on the provided admission panel request.
    /// </summary>
    /// <param name="request">The admission panel request containing the patient location details to update.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the update was successful; otherwise, <c>false</c>.</returns>
    Task<bool> UpdatePatientLocation(AdmPanelRequest request);
    /// <summary>
    /// Updates the patient data based on the provided admission panel request, using the existing patient record as a reference.
    /// </summary>
    /// <param name="request">The admission panel request containing the updated patient data.</param>
    /// <param name="oldPatient">The existing patient record to be updated.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the patient data was successfully updated; otherwise, <c>false</c>.</returns>
    Task<bool> UpdatePatientData(AdmPanelRequest request, Patient oldPatient);
    /// <summary>
    /// Archives the specified patient, marking them as inactive while preserving their record.
    /// </summary>
    /// <param name="patient">The patient to be archived.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains <c>true</c> if the patient was successfully archived; otherwise, <c>false</c>.</returns>
    Task<bool> ArchivePatient(Patient patient);

    #endregion

    #region ConfigObservations
    /// <summary>
    /// Asynchronously creates a configuration based on the specified observation.
    /// </summary>
    /// <param name="configObservation">The observation data used to create the configuration.</param>
    /// <returns>A task that represents the asynchronous create operation, containing a value indicating whether the configuration was created successfully.</returns>
    Task<bool> CreateConfig(ConfigObservation configObservation);
    /// <summary>
    /// Asynchronously updates the configuration based on the provided <see cref="ConfigObservation"/>, applying any required changes derived from the observation data.
    /// </summary>
    /// <param name="configObservation">The observation data used to determine and apply configuration updates.</param>
    /// <returns>A <see cref="Task{Boolean}"/> that represents the asynchronous update operation, containing a value indicating whether the configuration was successfully updated.</returns>
    Task<bool> UpdateConfig(ConfigObservation configObservation);
    /// <summary>
    /// Deletes the configuration observation item identified by the specified identifier.
    /// </summary>
    /// <param name="id">The unique identifier of the configuration observation item to delete.</param>
    /// <returns>A task that represents the asynchronous operation. The task result is <c>true</c> if the item was successfully deleted; otherwise, <c>false</c>.</returns>
    Task<bool> DeleteConfigObservationItem(ObjectId id);

    #endregion

    #region Medicienes

    /// <summary>
    /// Retrieves a <see cref="Medicine"/> entity by its unique identifier from the data store.
    /// Returns <c>null</c> when no medicine matches the provided identifier.
    /// </summary>
    /// <param name="medicineId">The unique <see cref="ObjectId"/> of the medicine to look up.</param>
    /// <returns>A <see cref="Task{Medicine}"/> that resolves to the matching <see cref="Medicine"/>, or <c>null</c> if not found.</returns>
    Task<Medicine?> GetMedicineById(ObjectId medicineId);
    /// <summary>
    /// Asynchronously creates and persists a new medicine record.
    /// </summary>
    /// <param name="medicine">The medicine entity to be created and posted.</param>
    /// <returns>A task that represents the asynchronous operation, containing the newly created <see cref="Medicine"/>, or <c>null</c> if the operation fails.</returns>
    Task<Medicine?> PostMedicine(Medicine medicine);
    /// <summary>
    /// Updates an existing medicine record in the system.
    /// </summary>
    /// <param name="medicine">The medicine entity containing the updated information to be persisted.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains the updated <see cref="Medicine"/> if found, or <c>null</c> if the medicine does not exist.</returns>
    Task<Medicine?> UpdateMedicine(Medicine medicine);
    /// <summary>
    /// Deletes a medicine identified by its unique identifier.
    /// </summary>
    /// <param name="medicineId">The unique identifier of the medicine to delete.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains <c>true</c> if the medicine was successfully deleted; otherwise, <c>false</c>.</returns>
    Task<bool> DeleteMedicineById(string medicineId);

    #endregion
}