using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Utils;

namespace adas_core.Domain.Models.Observations;

public class Medication : Observation
{
    public Medication()
    {
    }

    public Medication(string id, Dictionary<string, PumpElement> obj)
    {
        if (obj.TryGetValue("MDC_184504", out var mode)) PumpMode = new PumpMode(mode);

        if (obj.TryGetValue("MDC_184519", out var status)) PumpStatus = new PumpStatus(status);

        if (obj.TryGetValue("MDC_157784", out var flow)) FlowFluid = new FlowFluid(flow);

        if (obj.TryGetValue("MDC_157993", out var fluid)) VolFluidTotal = new VolumeFluidDeliveryTotal(fluid);

        if (obj.TryGetValue("MDCX_PUMP_DELIVERY_PRESSURE", out var pressure))
            PumpDeliveryPressure = new PumpDeliveryPressure(pressure);

        if (obj.TryGetValue("MDC_DEV_PUMP_ACTIVE_SOURCES", out var source))
            PumpActiveSources = new PumpActiveSources(source);

        if (obj.TryGetValue("MDC_184514", out var drug)) Drug = new Drug(drug);

        if (obj.TryGetValue("MDC_157872", out var volume)) VolumeFluidTbiRemain = new VolumeFluidTbiRemain(volume);

        if (obj.TryGetValue("MDC_157916", out var remain)) VolumeFluidTimeRemain = new VolumeFluidTimePdRemain(remain);

        Id = id;
    }

    public string? Id { get; set; }
    public PumpMode? PumpMode { get; set; }
    public PumpStatus? PumpStatus { get; set; }
    public FlowFluid? FlowFluid { get; set; }
    public VolumeFluidDeliveryTotal? VolFluidTotal { get; set; }
    public VolumeFluidTbiRemain? VolumeFluidTbiRemain { get; set; }
    public VolumeFluidTimePdRemain? VolumeFluidTimeRemain { get; set; }
    public PumpDeliveryPressure? PumpDeliveryPressure { get; set; }
    public PumpActiveSources? PumpActiveSources { get; set; }
    public Drug? Drug { get; set; }
}

public class DrugValue
{
    public DrugValue()
    {
    }

    public DrugValue(PumpElement pumpElement)
    {
        Id = pumpElement.Id;
        Text = pumpElement.Text;
        Time = pumpElement.Time;
        Units = pumpElement.Units;
        CodingSystem = pumpElement.CodingSystem;
        Result = pumpElement.Result;
    }

    public string? Id { get; set; }
    public string? Text { get; set; }
    public string? Units { get; set; }
    public DateTime? Time { get; set; }
    public string? CodingSystem { get; set; }
    public char? Result { get; set; } = 'R';

    public void Copy(DrugValue common)
    {
        Id = common.Id;
        Text = common.Text;
        Units = common.Units;
        Time = common.Time;
        CodingSystem = common.CodingSystem;
        Result = common.Result;
    }
}

public abstract class DrugDoubleValue : DrugValue
{
    protected DrugDoubleValue(PumpElement pumpElement) : base(pumpElement)
    {
        if (double.TryParse(pumpElement.Value?.ToString(), out var valueParsed))
            Value = valueParsed;
    }

    public double? Value { get; set; }
}

public abstract class DrugStringValue(PumpElement pumpElement) : DrugValue(pumpElement)
{
    public string? Value { get; set; } = pumpElement.Value?.ToString();
}

public class FlowFluid(PumpElement pumpElement) : DrugDoubleValue(pumpElement);

public class VolumeFluidDeliveryTotal(PumpElement pumpElement) : DrugDoubleValue(pumpElement);

public class PumpDeliveryPressure(PumpElement pumpElement) : DrugDoubleValue(pumpElement);

public class VolumeFluidTbiRemain(PumpElement pumpElement) : DrugDoubleValue(pumpElement);

public class VolumeFluidTimePdRemain(PumpElement pumpElement) : DrugDoubleValue(pumpElement);

public class PumpActiveSources(PumpElement pumpElement) : DrugStringValue(pumpElement)
{
    public string? ValueId { get; set; } = pumpElement.ValueId;
    public string? ValueCodingSystem { get; set; } = pumpElement.ValueCodingSystem;
}

public class Drug(PumpElement pumpElement) : DrugStringValue(pumpElement);

public class PumpMode : DrugStringValue
{
    public PumpMode(PumpElement pumpElement) : base(pumpElement)
    {
        Value = pumpElement.Value?.ToString()?.SubstringAfter("pump-mode-").Replace("-", "_");
    }
}

public class PumpStatus : DrugStringValue
{
    public PumpStatus(PumpElement pumpElement) : base(pumpElement)
    {
        Value = pumpElement.Value?.ToString()?.SubstringAfter("pump-status-").Replace("-", "_");
    }
}