using System.Text.Json;
using adas_core.Domain.Enums;

namespace adas_core.Domain.Models.AppSettings;

/// <summary>
/// Represents configuration settings for an API, such as base URL, authentication credentials, and timeout values.
/// </summary>
public class ApiSettings
{
    public const string Api = "ApiSettings";
    public string? Customize { get; set; }
    public PointOfCareMapping? PointOfCareMapping { get; set; }
    public ConfigObservationSettings? ConfigObservation { get; set; }

    public RetentionPolicy RetentionPolicy { get; set; }
    public int RetentionPolicyValue { get; set; }

    //public CacheSettings? CacheSettings { get; set; }
    public bool CreatePatientWithOru { get; set; }
    public bool PushPatientWithOru { get; set; }
    public bool CreatePatientWithSiu { get; set; }
    public bool CreatePatientWithoutLocation { get; set; }
    public bool CreatePatientWithoutPatientNumber { get; set; }
    public bool CreatePatientWithLocation { get; set; }
    public bool CreatePatientWithAdtA08 { get; set; }
    public bool UpdatePatientDataWithOru { get; set; }
    public bool UpdatePatientDataWithAdtA02 { get; set; }
    public bool UpdatePatientLocationWithOru { get; set; }
    public bool UpdatePatientNumberWithOru { get; set; }

    public bool ActivateSchedulerCheckNewsJob { get; set; }

    public int CheckNewsJobIntervalMinutes { get; set; } = 15;

    public string? PatientsAppointments { get; set; }
    public string? PatientsDiagnosis { get; set; }
    public string? PatientsObservations { get; set; }
    public string? PatientsAlarms { get; set; }
    public string? Patients { get; set; }
    public string? PoCSettings { get; set; }
    public string? PumpObservations { get; set; }
    public string? PumpStates { get; set; }
    public string? PumpAlarmEvent { get; set; }
    public string? PumpAlarmState { get; set; }
    
    public string? PatientsRecordingAlerts { get; set; }
    public string? PatientsTreatments { get; set; }
    public string Mappings { get; set; } = "mappings";
    public string? ConfigSections { get; set; }
    public string? Units { get; set; } = "units";
    public string? ConfigObservations { get; set; }
    public string? HistoricalConfigChanges { get; set; }

    public string Admissions { get; set; } = "admissions";
    public string Discharges { get; set; } = "discharges";
    public string Notices { get; set; } = "notices";
    public string Locations { get; set; } = "pointOfCares";
    public string Relays { get; set; } = "relays";
    public string Cameras { get; set; } = "cameras";
    public string LightBeacons { get; set; } = "light_beacons";
    public string Displays { get; set; } = "displays";
    public string DisplaysConfig { get; set; } = "config_displays";
    public string DisplayCardConfig { get; set; } = "config_displays_card";
    public string DisplayDetailConfig { get; set; } = "config_displays_detail";
    public string DisplayChartConfig { get; set; } = "config_displays_chart";
    public string Authorizations { get; set; } = "authorizations";


    public string AltableOptionList { get; set; } = "list_altable";
    public string AllergyList { get; set; } = "list_allergy";
    public string DestinationList { get; set; } = "list_destinations";
    public string DiagnosisList { get; set; } = "list_diagnosis";
    public string DischargeStatusList { get; set; } = "list_dischargeStatus";
    public string DoctorList { get; set; } = "list_doctor";
    public string DoctorTypeList { get; set; } = "list_doctorType";
    public string InternalDestinationList { get; set; } = "list_internalDestination";
    public string InsulationList { get; set; } = "list_insulation";
    public string LanguageBarrierList { get; set; } = "list_languageBarrier";
    public string MobilityOptionList { get; set; } = "list_mobility";
    public string OriginList { get; set; } = "list_origin";
    public string PatientStatusList { get; set; } = "list_patientStatus";
    public string ProcedureList { get; set; } = "list_procedure";
    public string TestList { get; set; } = "list_test";
    public string ServiceList { get; set; } = "list_service";
    public string TherapeuticCeilingList { get; set; } = "list_therapeuticCeiling";
    public string TreatmentList { get; set; } = "list_treatment";
    public string VisitOptionList { get; set; } = "list_visitOption";
    public string AccessControlList { get; set; } = "list_accessControl";
    public string PassiveSittingList { get; set; } = "list_passiveSitting";
    public string GenericList { get; set; } = "list_generic";
    

    public string? ConfigUnits { get; set; }
    public bool ConfigUnitsRequired { get; set; } = true;
    public string? ConfigUnitsKey { get; set; }

    public string? ConfigPumps { get; set; }
    public bool ConfigPumpsRequired { get; set; } = true;
    public string? ConfigPumpsKey { get; set; }

    public string? ServiceConfig { get; set; }
    public string Users { get; set; } = "users";
    public string? Medicines { get; set; }


    public string? Devices { get; set; }
    public string? ArchivePatientsAppointments { get; set; }
    public string? ArchivePatientsDiagnosis { get; set; }
    public string? ArchivePatientsObservations { get; set; }
    public string? ArchivePatient { get; set; }
    public string? ArchivePatientsPumpobservations { get; set; }
    public string? ArchivePatientsRecordingalerts { get; set; }
    public string? ArchivePatientsTreatments { get; set; }
    public string? ArchivePatientProcedure { get; set; }
    public string? PatientCarePlan { get; set; }
    public bool CretatePatientWithoutPatientNumber { get; set; }
    public bool ArchivePatientWithOru { get; set; }
    public string? OnArchivePatientAction { get; set; }
    public int? ArchivePatientsWithoutObservationsSinceHours { get; set; }
    public int? CheckInactivePatientSchedulerIntervalHours { get; set; }
    public int? CheckActiveTreatmentsSchedulerIntervalMinutes { get; set; }
    public int? CheckActiveAppointmentsSchedulerIntervalMinutes { get; set; }

    public int? GetProvidersObservationsSchedulerIntervalMinutes { get; set; }
    public int? SinceDischargeTimeToArchive { get; set; }
    public int? CheckErrorQueues { get; set; }

    public bool ActivateCheckExpiredAlerts { get; set; } = true;
    public bool ActivateSchedulerCheckExpiredObservation { get; set; }
    public bool ActivateSchedulerGetProvidersObservations { get; set; }
    public bool ActivateCheckInactivePatients { get; set; }
    public bool ActivateSchedulerCheckOpiateBoluses { get; set; }
    public bool ActivateSchedulerCheckActiveTreatmentsJob { get; set; }
    public bool ActivateSchedulerCheckActiveAppointmentsJob { get; set; }

    public bool ActivateSchedulerCheckHydricBalance { get; set; }


    public int? SchedulerCheckExpiredObservationsIntervalMinutes { get; set; }
    public int? SchedulerCheckExpiredAlertsIntervalSeconds { get; set; }

    public bool StartRecordingWithoutPatientNumber { get; set; } = true;

    public List<string>? Shift { get; set; }
    public bool FindPatientByLocationWithoutId { get; set; }
    public bool PersistObservationCodes { get; set; }
    public string? IccaFacility { get; set; }
    public List<string>? SendingFacility { get; set; }
    public List<string> AllergiesCode { get; set; } = [];
    public List<string> DrainageCode { get; set; } = [];
    public List<string> PositionCode { get; set; } = [];
    public List<string> IsolationCode { get; set; } = [];
    public List<string>? HighFrequencyVentilation { get; set; }
    public List<string>? InvasiveVentilation { get; set; }
    public List<string>? NonInvasiveVentilation { get; set; }
    public List<string>? Ecmo { get; set; }
    public List<string>? Surgery { get; set; }
    public List<string>? Sedation { get; set; }
    public List<string>? AntibioticList { get; set; }
    public List<string>? AnxiolyticList { get; set; }
    public List<string>? AntipsicoticList { get; set; }
    public List<string>? AntidepressantsList { get; set; }
    public List<string>? NeuroMedicationList { get; set; }
    public List<string>? SerumCrystalloidList { get; set; }
    public List<string>? SerumColloidList { get; set; }
    public List<string>? AntihypertensivesList { get; set; }
    public List<string>? SurgeryText { get; set; }
    public List<string>? Transcutaneous { get; set; }
    public List<string>? RegionalBrainSaturation { get; set; }
    public List<string>? MedicationBolus { get; set; }
    public List<string>? NotesIndicatingMedication { get; set; }
    public List<string>? IntravenousLinesCode { get; set; }
    public List<string>? Electroencephalogram { get; set; }
    public List<string>? Respiratory { get; set; }
    public List<string>? Oni { get; set; }
    public List<string>? PumPressureAlarm { get; set; }
    public List<string>? VolumetricAirOcclusionAlarm { get; set; }
    public List<string>? VolumetricAirInLineAlarm { get; set; }

    public List<string>? EndContinuousInfusionAlarm { get; set; }
    public List<string>? InotropicEndInfusionAlarm { get; set; }

    public List<string>? InotropicMedicines { get; set; }
    public int IgnoreCalcObservationsOlderInMinutesThan { get; set; }
    public int PumpExpiresSeconds { get; set; } = 60;
    public bool SendPumpsZero { get; set; } = true;

    public string? BalizaUrl { get; set; }
    public string? BalizaPassword { get; set; }
    public string? DiagnosisSystem { get; set; }
    public List<string> DiagnosisCode { get; set; } = [];


    public string[]? PathUpdateFiles { get; set; }
    public int? TimeToSendGroupedObs { get; set; }
    public string[]? PathToDisplayAssets { get; set; }
    public List<string>? DefaultIdRecord { get; set; }

    public bool CalculateExtremeEvents { get; set; } = true;
    public double CalculateRespRateVentExpires { get; set; } = 2;

    public bool ActivateExpireAlertsTimer { get; set; }
    public int ExpireAlertIntervalSeconds { get; set; } = 5;

    public ArchiveNurseData ArchiveNurseData { get; set; } = new();
    public List<MappingInterventions>? MappingInterventions { get; set; }
    public Dictionary<string, int>? ComplexityMappingObservation { get; set; }


    public string? NoCalculateStatusWithCodingSystem { get; set; }
}

/// <summary>
/// Represents archived data related to a nurse, providing storage or transfer of historical nursing records.
/// </summary>
public class ArchiveNurseData
{
    public bool Active { get; set; } = false;
    public ArchiveNurseDataConfig ArchiveTest { get; set; } = new();
    public ArchiveNurseDataConfig ArchiveProcedure { get; set; } = new();
    public ArchiveNurseDataConfig ArchiveTreatment { get; set; } = new();
    public int IntervalMinutes { get; set; } = 15;
}

/// <summary>
/// Represents the configuration settings used to control the archiving process for nurse-related data.
/// </summary>
public class ArchiveNurseDataConfig
{
    public bool Active { get; set; } = false;
    public int EndDateAfterMinutes { get; set; } = 60;
}

/// <summary>
/// Represents a mapping configuration for point of care data, defining relationships between source and target structures.
/// </summary>
public class PointOfCareMapping
{
    public string? Key { get; set; }
    public bool Required { get; set; }
    public int? Refresh { get; set; } = 600; //10min
}

/// <summary>
/// Represents configuration settings that govern how observations are captured, processed, or reported.
/// </summary>
public class ConfigObservationSettings
{
    public bool IgnoreUnknownObservation { get; set; }
    public bool IgnoreUnknownTreatment { get; set; }
    public int? Refresh { get; set; }
}

#region CCC mapping config

/// <summary>
/// Represents a collection or registry of intervention codes used to identify or categorize specific interventions.
/// </summary>
public class InterventionsCodes
{
    private object? _finalValue;
    private object? _initialValue;

    public object? InitialValue
    {
        get => _initialValue switch
        {
            double d => d,
            string s => s,
            int i => (double)i,
            _ => null
        };
        set
        {
            switch (value)
            {
                case double:
                case string:
                    _initialValue = value;
                    break;
                case int intValue:
                    _initialValue = (double)intValue;
                    break;
                case JsonElement element:
                    switch (element.ValueKind)
                    {
                        case JsonValueKind.Number:
                            _initialValue = element.GetDouble();
                            return;
                        case JsonValueKind.String:
                            _initialValue = element.GetString();
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                    break;
                default:
                {
                    if (value != null)
                        try
                        {
                            _initialValue = Convert.ToDouble(value);
                        }
                        catch (FormatException)
                        {
                            try
                            {
                                _initialValue = value.ToString();
                            }
                            catch (Exception ex)
                            {
                                throw new ArgumentException(
                                    $"The value must be a double or a string. Received type: {value.GetType()}, Value: {value}, Error: {ex.Message}");
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new ArgumentException(
                                $"The value must be a double or a string. Received type: {value.GetType()}, Value: {value}, Error: {ex.Message}");
                        }
                    else
                        _initialValue = null;

                    break;
                }
            }
        }
    }

    public object? FinalValue
    {
        get => _finalValue switch
        {
            double d => d,
            string s => s,
            _ => null
        };
        set
        {
            // Apply the same JsonElement handling logic here as well
            if (value is double)
                _finalValue = value;
            else if (value is string)
                _finalValue = value;
            else if (value is JsonElement element)
                switch (element.ValueKind)
                {
                    case JsonValueKind.Number:
                        _finalValue = element.GetDouble();
                        return;
                    case JsonValueKind.String:
                        _finalValue = element.GetString();
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            else if (value != null)
                try
                {
                    _finalValue = Convert.ToDouble(value);
                }
                catch (FormatException)
                {
                    try
                    {
                        _finalValue = value.ToString();
                    }
                    catch (Exception ex)
                    {
                        throw new ArgumentException(
                            $"The value must be a double or a string. Received type: {value.GetType()}, Value: {value}, Error: {ex.Message}");
                    }
                }
                catch (Exception ex)
                {
                    throw new ArgumentException(
                        $"The value must be a double or a string. Received type: {value.GetType()}, Value: {value}, Error: {ex.Message}");
                }
            else
                _finalValue = null;
        }
    }
}

/// <summary>
/// Represents a collection or container of values related to interventions.
/// </summary>
public class InterventionsValues
{
    private object? _finalValue;
    private object? _initialValue;

    public object? InitialValue
    {
        get => _initialValue switch
        {
            double d => d,
            string s => s,
            _ => null
        };
        set
        {
            if (value is double)
                _initialValue = value;
            else if (value is string)
                _initialValue = value;
            else if (value is JsonElement element)
                switch (element.ValueKind)
                {
                    case JsonValueKind.Number:
                        _initialValue = element.GetDouble();
                        return;
                    case JsonValueKind.String:
                        _initialValue = element.GetString();
                        break;
                }
            else if (value != null)
                try
                {
                    _initialValue = Convert.ToDouble(value);
                }
                catch (FormatException)
                {
                    try
                    {
                        _initialValue = value.ToString();
                    }
                    catch (Exception ex)
                    {
                        throw new ArgumentException(
                            $"The value must be a double or a string. Received type: {value.GetType()}, Value: {value}, Error: {ex.Message}");
                    }
                }
                catch (Exception ex)
                {
                    throw new ArgumentException(
                        $"The value must be a double or a string. Received type: {value.GetType()}, Value: {value}, Error: {ex.Message}");
                }
            else
                _initialValue = null;
        }
    }

    public object? FinalValue
    {
        get => _finalValue switch
        {
            double d => d,
            string s => s,
            _ => null
        };
        set
        {
            if (value is double)
                _finalValue = value;
            else if (value is string)
                _finalValue = value;
            else if (value is JsonElement element)
                switch (element.ValueKind)
                {
                    case JsonValueKind.Number:
                        _finalValue = element.GetDouble();
                        return;
                    case JsonValueKind.String:
                        _finalValue = element.GetString();
                        break;
                }
            else if (value != null)
                try
                {
                    _finalValue = Convert.ToDouble(value);
                }
                catch (FormatException)
                {
                    try
                    {
                        _finalValue = value.ToString();
                    }
                    catch (Exception ex)
                    {
                        throw new ArgumentException(
                            $"The value must be a double or a string. Received type: {value.GetType()}, Value: {value}, Error: {ex.Message}");
                    }
                }
                catch (Exception ex)
                {
                    throw new ArgumentException(
                        $"The value must be a double or a string. Received type: {value.GetType()}, Value: {value}, Error: {ex.Message}");
                }
            else
                _finalValue = null;
        }
    }

    public int ValueContributed { get; set; } = 0;
}

/// <summary>
/// Represents a collection or configuration for mapping interventions, providing the means to associate intervention data with corresponding target structures or actions.
/// </summary>
public class MappingInterventions
{
    public string? Type { get; set; }
    public string? Group { get; set; }
    public string? Name { get; set; }
    public ObservationEnum.Category? Category { get; set; }
    public List<InterventionsCodes> Codes { get; set; } = [];
    public List<InterventionsValues>? Value { get; set; }
}

#endregion