using adas_core.Domain.Enums;
using adas_core.Domain.Models.Masters;
using MongoDB.Bson;

namespace adas_core.Domain.Models.MongoModels;

public class Patient
{
    public ObjectId Id { get; set; }

    public string? PatientNumber { get; set; }

    public string? PatientId { get; set; }

    public DateTime? AdmTime { get; set; }

    //Estado del Alta: Altable, no Altable, Exitus, Transferible
    public OptionList? DischargeStatus { get; set; }

    public OptionList? Altable { get; set; }

    //Procedencia
    public OptionList? Origin { get; set; }

    public string? OriginAux { get; set; }

    //Diagnósticos
    public OptionList? Diagnosis { get; set; }

    public string? DiagnosisAux { get; set; }

    //Visitas
    public OptionList? Visits { get; set; }

    public OptionList? AccessControl { get; set; }

    //Aislamiento: por defecto No Aislado
    public OptionList? Insulation { get; set; }

    //NEMS
    public OptionList? PatientStatus { get; set; }

    //Movilidad: por defecto sin asignar
    public OptionList? Mobility { get; set; }

    //Techo terapeutico
    public OptionList? TherapeuticCeiling { get; set; }

    // Intervenciones
    public List<OptionList>? Procedures { get; set; }

    //Pruebas (tests)
    public List<OptionList>? Tests { get; set; }

    //Terapias
    public List<OptionList>? Treatment { get; set; }

    //Facultativos
    public List<OptionList>? Doctors { get; set; }

    //Alergias
    public List<OptionList>? Allergies { get; set; }

    public List<OptionList>? LanguageBarrier { get; set; }
    public OptionList? PassiveSitting { get; set; }

    public DateTime? DisTime { get; set; }

    public Person? Person { get; set; }

    public Person? AttendingDoctor { get; set; }

    public DateTime? LastObservationDate { get; set; }

    public DateTime? CreationDate { get; set; }

    public DateTime? UpdateDate { get; set; }

    public DateTime? ArchiveDate { get; set; }

    public ObjectId? PointOfCareId { get; set; }

    public ObjectId? UnitId { get; set; }
    
    public List<HistoricalLocation>? HistoricalLocations { get; set; }

    public override string ToString()
    {
        List<string> items = [$"id: {Id}"];
        if (!string.IsNullOrEmpty(UnitString)) items.Add($"pointOfCare: {UnitString}");
        if (!string.IsNullOrEmpty(Bed)) items.Add($"bed: {Bed}");
        if (!string.IsNullOrEmpty(PatientNumber)) items.Add($"patientNumber: {PatientNumber}");
        if (!string.IsNullOrEmpty(PatientId)) items.Add($"patientId: {PatientId}");
        if (AdmTime.HasValue) items.Add($"admTime: {AdmTime}");
        if (DisTime.HasValue) items.Add($"disTime: {DisTime}");
        if (Person != null) items.Add($"patient: {Person}");
        if (AttendingDoctor != null) items.Add($"attendingDoctor: {AttendingDoctor}");
        if (LastObservationDate.HasValue) items.Add($"lastObservationDate: {LastObservationDate}");
        if (CreationDate.HasValue) items.Add($"creationDate: {CreationDate}");
        if (UpdateDate.HasValue) items.Add($"updateDate: {UpdateDate}");
        if (ArchiveDate.HasValue) items.Add($"archiveDate: {UpdateDate}");
        return "person[" + string.Join(", ", items) + "]";
    }

    public bool IsInActivePoC()
    {
        return UnitString != null && !Enum.IsDefined(typeof(VirtualPointOfCare), UnitString);
    }

    public Patient DeepCopy()
    {
        return (Patient)MemberwiseClone();
    }

    #region UnMap

    public string? Bed { get; set; }
    public string? Room { get; set; }
    public string? UnitString { get; set; }
    public PointOfCare? PointOfCare { get; set; }

    public PatientLocation Location
    {
        get => new(UnitString, Bed, Room ?? Bed);
        set
        {
            if (value == null || (UnitString == value.UnitName && Bed == value.Bed)) 
                return;

            UnitString = value.UnitName;
            Bed = value.Bed;
            HistoricalLocations ??= [];

            var currentUtc = DateTime.UtcNow;

            bool shouldAdd = true;
            if (HistoricalLocations.Count > 0)
            {
                var last = HistoricalLocations[^1];
                if (last.PatientLocation?.Bed == value.Bed && last.PatientLocation?.UnitName == value.UnitName)
                {
                    shouldAdd = false;
                }
                else if (currentUtc.ToString("o").Equals(last.AdmTime.ToString()))
                {
                    currentUtc = currentUtc.AddSeconds(1);
                }
            }

            if (shouldAdd)
            {
                HistoricalLocations.Add(new HistoricalLocation(
                    currentUtc, 
                    new PatientLocation(value.UnitName, value.Bed, value.Room)
                ));
            }
        }
    }

    #endregion
}

public class PatientIncomeData
{
    public DateTime? AdmTime { get; set; }
    public OptionList? Origin { get; set; }
    public string? OriginAux { get; set; }
    public OptionList? Diagnosis { get; set; }
    public string? DiagnosisAux { get; set; }
}