using adas_core.Application.Customizations.H12O.UCIN;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using Moq;
using Options = Microsoft.Extensions.Options.Options;

namespace adas_core.Test.Customizations.H12O.UCIN;

[TestFixture]
[Order(2)]
public class CalculatedObservationsTest
{
    [SetUp]
    public void Setup()
    {
        _observationServiceMock = new Mock<IObservationService>();

        _configOservationServiceMock = new Mock<IConfigObservationService>();

        _medicineServiceMock = new Mock<IMedicineService>();

        _treatmentServiceMock = new Mock<ITreatmentService>();

        _logger = new Mock<ILogger<CalculatedObservations>>();

        _optionsApiSettings = Options.Create(_apiSettings);

        _optionsApiSettings.Value.MedicationBolus = ["18851000140100", "21011000140105"];
        _optionsApiSettings.Value.IntravenousLinesCode = ["10546003"];
        _optionsApiSettings.Value.Transcutaneous = ["151756", "151760"];
        _optionsApiSettings.Value.RegionalBrainSaturation = ["194908", "194909"];
        _optionsApiSettings.Value.Electroencephalogram = ["42803009"];
        _optionsApiSettings.Value.Respiratory = ["361110005", "84481000140102"];
        _optionsApiSettings.Value.HighFrequencyVentilation = ["PC-HFO"];
        _optionsApiSettings.Value.InvasiveVentilation =
        [
            "A/C  (S.I.P.P.V. )", "A/C  (S.I.P.P.V.) + V.G.", "PRVC", "PC-SIMV", "SIMV-PRVC", "PC-AC", "SIMV",
            "SIMV-PC", "S.I.M.V.", "PC-CMV", "SIPPV", "PC"
        ];
        _optionsApiSettings.Value.NonInvasiveVentilation = ["DUOPAP", "NCPAP"];
        _optionsApiSettings.Value.Oni = ["84481000140102", "416362002"];
        _optionsApiSettings.Value.Ecmo = ["705923009"];
        var serviceCollection = new ServiceCollection();
        //serviceCollection.AddSingleton(_observationServiceMock.Object);
        serviceCollection.AddSingleton(new Lazy<IObservationService>(() => _observationServiceMock.Object));

        serviceCollection.AddSingleton(
            new Lazy<IConfigObservationService>(() => _configOservationServiceMock.Object));
        serviceCollection.AddSingleton(_medicineServiceMock.Object);
        serviceCollection.AddSingleton(new Lazy<ITreatmentService>(() => _treatmentServiceMock.Object));
        serviceCollection.AddSingleton(_optionsApiSettings);
        serviceCollection.AddSingleton(_logger.Object);

        var serviceProvider = serviceCollection.BuildServiceProvider();

        _calculatedObservations = new CalculatedObservations(serviceProvider);
    }

    private CalculatedObservations _calculatedObservations;
    private Mock<IMedicineService> _medicineServiceMock;
    private Mock<IObservationService> _observationServiceMock;
    private Mock<IConfigObservationService> _configOservationServiceMock;
    private Mock<ITreatmentService> _treatmentServiceMock;
    private Mock<ILogger<CalculatedObservations>> _logger;

    private readonly ApiSettings _apiSettings = new()
    {
        ConfigObservation = new ConfigObservationSettings
        {
            IgnoreUnknownObservation = false
        }
    };

    private IOptions<ApiSettings> _optionsApiSettings;

    [Test]
    public async Task Calculate_First_Medicine_Observation_With_Type_Should_Return_1()
    {
        //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1
        var patientId = ObjectId.GenerateNewId();

        var treatment =
            new PatientTreatment
            {
                Id = ObjectId.GenerateNewId(),
                PatientId = patientId,
                OrderControl = OrderControlType.Nw,
                PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                RequestedGiveCodes = [new Code { Identifier = "12345" }],
                OrderStatus = "A",
                OrderTime = DateTime.Now,
                Notes = [],
                Routes = []
            };

        var medicine =
            new Medicine
            {
                Codes = ["12345"],
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Type = [MedicineEnum.Types.MuscleRelaxant.ToString()],
                Name = "cisataracurio"
            };

        _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List<string> { "12345" }))
            .ReturnsAsync([medicine]);
        _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, true));
        _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);
        _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId))
            .ReturnsAsync(new List<PatientTreatment>().AsEnumerable());
        _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
            .ReturnsAsync(new List<Medicine>().AsEnumerable());


        await _calculatedObservations.Map(treatment);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Medication" && (int)arg.Value == 1 && arg.PatientId == patientId
        ), true, false));
    }


    [Test]
    public async Task Calculate_First_Medicine_Observation_With_Out_Type_Should_Return_1()
    {
        //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1
        var patientId = ObjectId.GenerateNewId();

        var treatment =
            new PatientTreatment
            {
                Id = ObjectId.GenerateNewId(),
                PatientId = patientId,
                OrderControl = OrderControlType.Nw,
                PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                RequestedGiveCodes = [new Code { Identifier = "12345" }],
                OrderStatus = "A",
                OrderTime = DateTime.Now,
                Notes = [],
                Routes = []
            };

        var medicine =
            new Medicine
            {
                Codes = ["12345"],
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Name = "cisataracurio"
            };

        _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List<string> { "12345" }))
            .ReturnsAsync([medicine]);
        _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, true));
        _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);
        _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId))
            .ReturnsAsync(new List<PatientTreatment>().AsEnumerable());
        _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
            .ReturnsAsync(new List<Medicine>().AsEnumerable());


        await _calculatedObservations.Map(treatment);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Medication" && (int)arg.Value == 0 && arg.PatientId == patientId
        ), true, false));
    }


    [Test]
    public async Task Calculate__Medicine_Observation_New_Type_Should_Sum_1()
    {
        //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1
        var patientId = ObjectId.GenerateNewId();

        var treatment =
            new PatientTreatment
            {
                Id = ObjectId.GenerateNewId(),
                PatientId = patientId,
                OrderControl = OrderControlType.Nw,
                PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                RequestedGiveCodes = [new Code { Identifier = "12345" }],
                OrderStatus = "A",
                OrderTime = DateTime.Now,
                Notes = [],
                Routes = []
            };

        var medicine =
            new Medicine
            {
                Codes = ["12345"],
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Name = "cisataracurio",
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            };

        _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId))
            .ReturnsAsync(new List<PatientTreatment>().AsEnumerable());
        _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List<string> { "12345" }))
            .ReturnsAsync([medicine]);
        _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
            .ReturnsAsync(new List<Medicine>().AsEnumerable());
        _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, true));


        _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(treatment);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Medication" && (int)arg.Value == 1 && arg.PatientId == patientId
        ), true, false));
    }


    [Test]
    public async Task Calculate__Medicine_Observation_Type_Already_Exists_Should_Sum_0()
    {
        //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1
        var patientId = ObjectId.GenerateNewId();

        var treatment =
            new PatientTreatment
            {
                Id = ObjectId.GenerateNewId(),
                PatientId = patientId,
                OrderControl = OrderControlType.Nw,
                PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                RequestedGiveCodes = [new Code { Identifier = "12345" }],
                OrderStatus = "A",
                OrderTime = DateTime.Now,
                Notes = [],
                Routes = []
            };

        var medicine =
            new Medicine
            {
                Codes = ["12345"],
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Name = "cisataracurio",
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            };

        var activeMedicines = new List<Medicine>
        {
            new()
            {
                Codes = ["12345"],
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Name = "Biotin",
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            }
        };

        _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId))
            .ReturnsAsync(new List<PatientTreatment>().AsEnumerable());
        _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List<string> { "12345" }))
            .ReturnsAsync([medicine]);
        _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
            .ReturnsAsync(activeMedicines.AsEnumerable());
        _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, true));
        _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([
                new PatientObservation
                {
                    PatientId = patientId,
                    Value = 0,
                    Name = "Medication"
                }
            ]);


        await _calculatedObservations.Map(treatment);


        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Medication"
            && (int)arg.Value == 1
            && arg.PatientId == patientId
        ), true, false));
    }


    [Test]
    public async Task Calculate__Medicine_Observation_DC_Type_Already_Exists_Should_Subtract_0()
    {
        var patientId = ObjectId.GenerateNewId();

        var treatment =
            new PatientTreatment
            {
                Id = ObjectId.GenerateNewId(),
                PatientId = patientId,
                OrderControl = OrderControlType.Dc,
                PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                RequestedGiveCodes = [new Code { Identifier = "12345" }],
                OrderStatus = "A",
                OrderTime = DateTime.Now,
                Notes = [],
                Routes = []
            };

        var medicine =
            new Medicine
            {
                Codes = ["12345"],
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Name = "cisataracurio",
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            };

        var activeMedicines = new List<Medicine>
        {
            new()
            {
                Codes = ["12345"],
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Name = "cisataracurio",
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            }
        };

        _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId))
            .ReturnsAsync(new List<PatientTreatment>().AsEnumerable());
        _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List<string> { "12345" }))
            .ReturnsAsync([medicine]);
        _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
            .ReturnsAsync(activeMedicines.AsEnumerable());
        _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, true));
        _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([
                new PatientObservation(patientId, 1, "Medication")
            ]);


        await _calculatedObservations.Map(treatment);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "ERMedication" && (int)arg.Value == 0 && arg.PatientId == patientId
        ), true, false));
    }


    [Test]
    public async Task Calculate__Medicine_Observation_DC_OF_TYPE_WITH_TWO_MEDICINES_Should_Subtract_0()
    {
        //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1
        var patientId = ObjectId.GenerateNewId();

        var treatment =
            new PatientTreatment
            {
                Id = ObjectId.GenerateNewId(),
                PatientId = patientId,
                OrderControl = OrderControlType.Dc,
                PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                RequestedGiveCodes = [new Code { Identifier = "12345" }],
                OrderStatus = "A",
                OrderTime = DateTime.Now,
                Notes = [],
                Routes = []
            };

        var medicine =
            new Medicine
            {
                Codes = ["12345"],
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Name = "cisataracurio",
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            };

        var activeMedicines = new List<Medicine>
        {
            new()
            {
                Codes = ["12345"],
                Name = "cisataracurio",
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            },

            new()
            {
                Codes = ["12345"],
                Name = "Lipoic acid",
                Group = [MedicineEnum.Group.DoubleSignature.ToString()],
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            }
        };

        _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId))
            .ReturnsAsync(new List<PatientTreatment>().AsEnumerable());
        _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List<string> { "12345" }))
            .ReturnsAsync([medicine]);
        _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
            .ReturnsAsync(activeMedicines.AsEnumerable());
        _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, false));

        _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([
                new PatientObservation
                {
                    PatientId = patientId,
                    Value = 2,
                    Name = "Medication"
                }
            ]);

        //_observationServiceMock.Setup(o => o.InsertObservation(It.Is<PatientObservation>(arg => 
        //    (arg.Name == "ERMedication" && (int)arg.Value == 1) 
        //    && arg.PatientId == patientId
        //), true, true));


        await _calculatedObservations.Map(treatment);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Medication"
            && (int)arg.Value == 1
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Medicine_Observation_New_Medicine_Without_Type_Should_Insert_Medication_1_point()
    {
        //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1
        var patientId = ObjectId.GenerateNewId();

        var treatment =
            new PatientTreatment
            {
                Id = ObjectId.GenerateNewId(),
                PatientId = patientId,
                OrderControl = OrderControlType.Nw,
                PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
                RequestedGiveCodes = [new Code { Identifier = "12345" }],
                OrderStatus = "A",
                OrderTime = DateTime.Now,
                Notes = [],
                Routes = []
            };

        var medicine =
            new Medicine
            {
                Codes = ["12345"],
                Name = "Betaine"
            };

        var activeMedicines = new List<Medicine>
        {
            new()
            {
                Codes = ["12345"],
                Name = "cisataracurio",
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            },

            new()
            {
                Codes = ["12345"],
                Name = "Lipoic acid",
                Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()]
            }
        };


        var expectedMedication = new PatientObservation
        {
            PatientId = patientId,
            Value = 0,
            Name = "Medication"
        };


        _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId))
            .ReturnsAsync(new List<PatientTreatment>().AsEnumerable());
        _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List<string> { "12345" }))
            .ReturnsAsync([medicine]);
        _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
            .ReturnsAsync(activeMedicines.AsEnumerable());
        _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, true));
        _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([expectedMedication]);


        await _calculatedObservations.Map(treatment);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Medication"
            && (int)arg.Value == 1
            && arg.PatientId == patientId
        ), true, false));
    }


    [Test]
    public async Task Calculate_First_Intravenous_Arterial_Observation_Should_Return_5()
    {
        var patientId = ObjectId.GenerateNewId();

        var obs = new PatientObservation
        {
            PatientId = patientId,
            Value = new PatientIntravenousLinesValue
            {
                Action = "Insert",
                Duration = "7",
                InsertTime = DateTime.Now,
                Location = "Rodilla",
                Type = "Catéter arterial"
            },
            Name = "IntravenousLinesObs"
        };


        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(obs, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "IntravenousLines"
            && (int)arg.Value == 5
            && arg.PatientId == patientId
        ), true, false));
    }


    [Test]
    public async Task Calculate_Intravenous_Obs_Already_Exist_Removed_Should_Return_0()
    {
        var patientId = ObjectId.GenerateNewId();
        var now = DateTime.Now;

        var obs = new PatientObservation
        {
            PatientId = patientId,
            Value = new PatientIntravenousLinesValue
            {
                Action = "Insert",
                Duration = "7",
                InsertTime = now,
                Location = "Rodilla",
                Type = "Catéter arterial",
                RemoveTime = DateTime.Now.AddDays(1)
            },
            Name = "IntravenousLinesObs"
        };

        _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId))
            .ReturnsAsync([]);

        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([
                new PatientObservation
                {
                    PatientId = patientId,
                    Value = new PatientIntravenousLinesValue
                    {
                        Action = "Insert",
                        Duration = "7",
                        InsertTime = now,
                        Type = "Catéter arterial",
                        Location = "Rodilla"
                    },
                    Name = "IntravenousLinesObs"
                }
            ]);

        await _calculatedObservations.Map(obs, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "IntravenousLines"
            && (int)arg.Value == 0
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Intravenous_two_observations_of_same_type_and_same_location_should_return_null()
    {
        var patientId = ObjectId.GenerateNewId();
        var now = DateTime.Now;

        var obs = new PatientObservation
        {
            PatientId = patientId,
            Name = "IntravenousLinesObs",
            Value = new PatientIntravenousLinesValue
            {
                Action = "Insertado",
                Duration = "7",
                InsertTime = now,
                Location = "Rodilla",
                Type = "Catéter arterial"
            }
        };

        _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId))
            .ReturnsAsync([
                new PatientObservation
                {
                    PatientId = patientId,
                    Value = new PatientIntravenousLinesValue
                    {
                        Action = "Insertado",
                        Duration = "7",
                        InsertTime = now,
                        Type = "Catéter arterial",
                        Location = "Rodilla"
                    },
                    Name = "IntravenousLinesObs"
                }
            ]);


        await _calculatedObservations.Map(obs, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "IntravenousLines"
            && (int)arg.Value == 5
            && arg.PatientId == patientId
        ), true, true), Times.Never);
    }

    [Test]
    public async Task Calculate_Intravenous_two_observations_of_same_type_should_return_10()
    {
        var patientId = ObjectId.GenerateNewId();
        var now = DateTime.Now;

        var obs = new PatientObservation
        {
            PatientId = patientId,
            Name = "IntravenousLinesObs",
            Value = new PatientIntravenousLinesValue
            {
                Action = "Insertado",
                Duration = "7",
                InsertTime = now,
                Location = "Rodilla",
                Type = "Catéter arterial"
            }
        };

        _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId))
            .ReturnsAsync([
                new PatientObservation
                {
                    PatientId = patientId,
                    Name = "IntravenousLinesObs",
                    Value = new PatientIntravenousLinesValue
                    {
                        Action = "Insertado",
                        Duration = "7",
                        InsertTime = now,
                        Type = "Catéter arterial",
                        Location = "Codo"
                    }
                }
            ]);

        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(obs, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "IntravenousLines"
            && (int)arg.Value == 10
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Intravenous_sum_more_than_10_should_limit_to_ten()
    {
        var patientId = ObjectId.GenerateNewId();
        var now = DateTime.Now;

        var obs = new PatientObservation
        {
            PatientId = patientId,
            Value = new PatientIntravenousLinesValue
            {
                Action = "Insertado",
                Duration = "7",
                InsertTime = now,
                Location = "Rodilla Izd.",
                Type = "Catéter arterial"
            },
            Name = "IntravenousLinesObs"
        };

        var patientObservations = new List<PatientObservation?>
        {
            new()
            {
                PatientId = patientId,
                Name = "IntravenousLinesObs",
                Value = new PatientIntravenousLinesValue
                {
                    Action = "Insertado",
                    Duration = "7",
                    InsertTime = now,
                    Type = "Catéter arterial",
                    Location = "Rodilla Der."
                }
            },
            new()
            {
                PatientId = patientId,
                Name = "IntravenousLinesObs",
                Value = new PatientIntravenousLinesValue
                {
                    Action = "Insertado",
                    Duration = "7",
                    InsertTime = now,
                    Type = "Catéter PICC",
                    Location = "Brazo"
                }
            }
        };

        _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId))
            .ReturnsAsync(patientObservations);
        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(obs, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "IntravenousLines"
            && (int)arg.Value == 10
            && arg.PatientId == patientId
        ), true, false));
    }


    [Test]
    public async Task Calculate_Intravenous_sum_one_middle_line_and_two_Peripheral_should_return_5()
    {
        var patientId = ObjectId.GenerateNewId();
        var now = DateTime.Now;

        var obs = new PatientObservation
        {
            PatientId = patientId,
            Value = new PatientIntravenousLinesValue
            {
                Action = "Insertado",
                Duration = "7",
                InsertTime = now,
                Location = "Rodilla Izd.",
                Type = "Catéter línea media"
            },
            Name = "IntravenousLinesObs"
        };

        _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId))
            .ReturnsAsync([
                new PatientObservation
                {
                    PatientId = patientId,
                    Name = "IntravenousLinesObs",
                    Value = new PatientIntravenousLinesValue
                    {
                        Action = "Insertado",
                        Duration = "7",
                        InsertTime = now,
                        Type = "Catéter EPICUTÁNEO PERIFÉRICO",
                        Location = "Rodilla Der."
                    }
                },

                new PatientObservation
                {
                    PatientId = patientId,
                    Name = "IntravenousLinesObs",
                    Value = new PatientIntravenousLinesValue
                    {
                        Action = "Insertado",
                        Duration = "7",
                        InsertTime = now,
                        Type = "Catéter Venoso PERIFÉRICO",
                        Location = "Brazo"
                    }
                }
            ]);

        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(obs, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "IntravenousLines"
            && (int)arg.Value == 5
            && arg.PatientId == patientId
        ), true, false));
    }


    [Test]
    public async Task Calculate_Monitor_Transcuatenous_Regional_Brain_Saturation_and_enter_EEG_should_return_3()
    {
        var patientId = ObjectId.GenerateNewId();

        var treatment = new PatientTreatment
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            OrderControl = OrderControlType.Nw,
            PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
            FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" },
            RequestedGiveCodes = [new Code { Identifier = "42803009" }],
            OrderStatus = "NW",
            OrderTime = DateTime.Now,
            Notes = [],
            Routes = []
        };


        _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId))
            .ReturnsAsync(new List<PatientTreatment>().AsEnumerable());
        _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List<string> { "42803009" }))
            .ReturnsAsync([]);

        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([
                new PatientObservation
                {
                    PatientId = patientId,
                    Code = "151756",
                    Name = "Transcutaneous",
                    Time = DateTime.Now
                },


                new PatientObservation
                {
                    PatientId = patientId,
                    Code = "151760",
                    Name = "Transcutaneous",
                    Time = DateTime.Now
                },


                new PatientObservation
                {
                    PatientId = patientId,
                    Code = "194908",
                    Name = "RegionalBrainSaturation",
                    Time = DateTime.Now
                },

                new PatientObservation
                {
                    PatientId = patientId,
                    Code = "194909",
                    Name = "RegionalBrainSaturation",
                    Time = DateTime.Now
                }
            ]);

        await _calculatedObservations.Map(treatment);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Monitor"
            && (int)arg.Value == 3
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Respiratory_INO_should_return_10()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "OXIDO NITRICO 800 PPM MOL",
            Code = "84481000140102",
            Name = "Tipo de ventilación",
            CodingSystem = "SNM"
        };


        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(observation, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Respiratory"
            && (int)arg.Value == 10
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Respiratory_VAFO_should_return_5()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "V.A.F.O.",
            Code = "361110005",
            Name = "Tipo de ventilación",
            CodingSystem = "SNM"
        };


        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(observation, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Respiratory"
            && (int)arg.Value == 5
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Respiratory_VMC_should_return_3()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "V.M.C.",
            Code = "361110005",
            Name = "Tipo de ventilación",
            CodingSystem = "SNM"
        };


        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(observation, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Respiratory"
            && (int)arg.Value == 3
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Respiratory_VMNI_should_return_2()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "V.N.I. Ciclada",
            Code = "361110005",
            Name = "Tipo de ventilación",
            CodingSystem = "SNM"
        };


        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(observation, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Respiratory"
            && (int)arg.Value == 2
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Respiratory_Nassal_Canulas_Bajo_Flujo_should_return_2()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "Bajo Flujo",
            Code = "361110005",
            Name = "Tipo de ventilación",
            CodingSystem = "SNM"
        };

        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);


        await _calculatedObservations.Map(observation, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Respiratory"
            && (int)arg.Value == 1
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Respiratory_Nassal_Canulas_Alto_Flujo_should_return_1()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "Alto Flujo",
            Code = "361110005",
            Name = "Tipo de ventilación",
            CodingSystem = "SNM"
        };


        _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.Map(observation, false);

        _observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
            arg.Name == "Respiratory"
            && (int)arg.Value == 1
            && arg.PatientId == patientId
        ), true, false));
    }

    [Test]
    public async Task Calculate_Ventilation_Mode_Returns_INVASIVE()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "PC-AC",
            Name = "Resp_Mode"
        };

        await _calculatedObservations.Map(observation, false);
        _observationServiceMock.Verify(o => o.InsertIfChanged("Resp_Type", It.Is<PatientObservation>(arg =>
            arg.Name == "Resp_Type" &&
            arg.CodingSystem == "ADAS" &&
            arg.Value.ToString() == RespirationType.Invasive.ToString()
        ), true, true));
    }

    [Test]
    public async Task Calculate_Ventilation_Mode_Returns_NON_INVASIVE()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "DUOPAP",
            Name = "Resp_Mode"
        };

        await _calculatedObservations.Map(observation, false);
        _observationServiceMock.Verify(o => o.InsertIfChanged("Resp_Type", It.Is<PatientObservation>(arg =>
            arg.Name == "Resp_Type" &&
            arg.CodingSystem == "ADAS" &&
            arg.Value.ToString() == RespirationType.NonInvasive.ToString()
        ), true, true));
    }

    [Test]
    public async Task Calculate_Ventilation_Mode_Returns_HIGH_FREQUENCY()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "PC-HFO",
            Name = "Resp_Mode"
        };

        await _calculatedObservations.Map(observation, false);
        _observationServiceMock.Verify(o => o.InsertIfChanged("Resp_Type", It.Is<PatientObservation>(arg =>
            arg.Name == "Resp_Type" &&
            arg.CodingSystem == "ADAS" &&
            arg.Value.ToString() == RespirationType.HighFrequencyVentilation.ToString()
        ), true, true));
    }

    [Test]
    public async Task Calculate_Ventilation_Mode_Returns_NONE()
    {
        var patientId = ObjectId.GenerateNewId();

        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Value = "VENTAPNEA",
            Name = "Resp_Mode"
        };

        await _calculatedObservations.Map(observation, false);
        _observationServiceMock.Verify(o => o.InsertIfChanged("Resp_Type", It.Is<PatientObservation>(arg =>
            arg.Name == "Resp_Type" &&
            arg.CodingSystem == "ADAS" &&
            arg.Value.ToString() == RespirationType.None.ToString()
        ), true, true));
    }

    [Test]
    public async Task CalculateOxygenationIndex_ShouldInsertCorrectObservation()
    {
        var patientId = ObjectId.GenerateNewId();
        var observation = new PatientObservation
        {
            PatientId = patientId,
            Name = "FiO2",
            Value = 50
        };

        var observations = new List<PatientObservation>
        {
            new() { Name = "AirPressure_Mean", Value = 20, PatientId = patientId },
            new() { Name = "FiO2", Value = 50, PatientId = patientId },
            new() { Name = "PaO2", Value = 80, PatientId = patientId }
        };

        _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync(observations);

        await _calculatedObservations.CalculateOxygenationIndex(observation);


        _observationServiceMock.Verify(s => s.InsertObservation(
            It.Is<PatientObservation>(o =>
                o.Name == "Oxygenation_Index" && o.PatientId == patientId && (int)o.Value == 1250),
            It.IsAny<bool>(), It.IsAny<bool>()));
    }

    [Test]
    public async Task CalculateAsistResp_ShouldUpdateObservation_WhenConditionsMet()
    {
        var patientId = ObjectId.GenerateNewId();
        var observation = new PatientObservation
        {
            PatientId = patientId,
            Name = "ONi",
            Value = "valor",
            Time = DateTime.Now,
            Code = "codigo"
        };

        var lastAsistResp = new PatientObservation
        {
            PatientId = patientId,
            Name = "Resp_Mode",
            Value = "valor",
            Time = DateTime.Now.AddMinutes(-10)
        };

        _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([lastAsistResp]);

        var result = await _calculatedObservations.CalculateAsistResp(observation);

        _observationServiceMock.Verify(s => s.InsertObservation(
            It.Is<PatientObservation>(o => o.Name == "Respiratory" && o.PatientId == patientId),
            It.IsAny<bool>(), It.IsAny<bool>()));

        Assert.That(result, Is.EqualTo(observation));
    }

    // [TestCase("valorHFV", RespirationType.HIGH_FREQUENCY_VENTILATION)]
    // [TestCase("valorInvasive", RespirationType.INVASIVE)]
    // [TestCase("valorNonInvasive", RespirationType.NON_INVASIVE)]
    // [TestCase("valorNone", RespirationType.NONE)]
    public async Task CalculateVentilationMode_ShouldInsertCorrectRespType(string value,
        RespirationType expectedRespType)
    {
        var patientId = ObjectId.GenerateNewId();
        var observation = new PatientObservation
        {
            PatientId = patientId,
            Name = "Resp_Mode",
            Time = DateTime.Now,
            Value = value switch
            {
                "valorHFV" => "PC-HFO",
                "valorInvasive" => "PRVC",
                "valorNonInvasive" => "DUOPAP",
                _ => expectedRespType
            }
        };
        await _calculatedObservations.CalculateVentilationMode(observation);

        _observationServiceMock.Verify(s => s.InsertIfChanged(
            "Resp_Type",
            It.Is<PatientObservation>(o =>
                o.PatientId == patientId && o.Name == "Resp_Type" && o.Value.ToString() == expectedRespType.ToString()),
            It.IsAny<bool>(), It.IsAny<bool>()));
    }


    // [TestCase("TAm", 10, 12, ObservationStatus.Ok)]
    // [TestCase("Age_Gestational", 1, 2, ObservationStatus.Alert)]
    // [TestCase("Age_Gestational", 1, 12, ObservationStatus.Ok)]
    // [TestCase("Age_Gestational_Fixed", 5, 10, ObservationStatus.Ok)]
    public async Task CalculateTAmAlert_ShouldUpdateStatusCorrectly(string observationName, int tamValue,
        int gestationalAge, StatusEnum.Type expectedType)
    {
        var patientId = ObjectId.GenerateNewId();
        var observation = new PatientObservation
        {
            PatientId = patientId,
            Name = observationName,
            Value = tamValue,
            Time = DateTime.Now,
            Status = expectedType
        };
        List<PatientObservation> groupedObservations = [];
        switch (observationName)
        {
            case "TAm":
                groupedObservations =
                [
                    new PatientObservation
                    {
                        Name = "Age_Gestational", Value = gestationalAge, PatientId = patientId,
                        Time = DateTime.Now.AddMinutes(-10), Status = expectedType
                    },
                    new PatientObservation
                    {
                        Name = "Age_Gestational_Fixed", Value = gestationalAge, PatientId = patientId,
                        Time = DateTime.Now.AddMinutes(-10), Status = expectedType
                    }
                ];
                break;
            case "Age_Gestational":
            case "Age_Gestational_Fixed":
                groupedObservations =
                [
                    new PatientObservation
                    {
                        Name = "Age_Gestational", Value = gestationalAge, PatientId = patientId,
                        Time = DateTime.Now.AddMinutes(-10), Status = expectedType
                    },
                    new PatientObservation
                    {
                        Name = "TAm", Value = tamValue, PatientId = patientId, Time = DateTime.Now.AddMinutes(-10),
                        Status = expectedType
                    }
                ];
                break;
        }

        _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync(groupedObservations);

        await _calculatedObservations.CalculateTAmAlert(observation);

        if (observation.Name == "TAm")
            Assert.That(observation.Status, Is.EqualTo(expectedType));
        else
            _observationServiceMock.Verify(s => s.InsertObservation(
                It.Is<PatientObservation>(o => o.PatientId == patientId && o.Name == "TAm"),
                It.IsAny<bool>(), It.IsAny<bool>()));
    }
    [Test]
    public async Task ParseWeight_WhenValidObservation_ShouldConvertUnitsAndValue()
    {
        var obs = new PatientObservation
        {
            Value = 1.23
        };

        var result = await _calculatedObservations.ParseWeight(obs) as PatientObservation;

        Assert.That(result, Is.Not.Null);

        Action assertions = () =>
        {
            Assert.That(result!.Units, Is.EqualTo("gr"));
            Assert.That(result.Value, Is.EqualTo(1230));
        };

        Assert.Multiple(assertions);
    }


    [Test]
    public async Task ParseWeight_WhenValueIsNotNumeric_ShouldHandleGracefullyAndReturnOriginal()
    {
        var obs = new PatientObservation
        {
            Value = "string"
        };
        var result = await _calculatedObservations.ParseWeight(obs);
        Assert.That(result, Is.EqualTo(obs));
    }

    [Test]
    public async Task ParseWeight_WhenInvalidObservation_ShouldReturnOriginal()
    {
        var obs = new BasePatientObservation(); // No es PatientObservation, por lo que no se puede convertir


        var result = await _calculatedObservations.ParseWeight(obs);

        Assert.That(result, Is.EqualTo(obs));
    }

    [Test]
    public async Task CalculateTempGradient_WhenTempPatientAndTempIncubatorAreRecent_ShouldCalculateGradient()
    {
        var now = DateTime.UtcNow;
        var patientId = ObjectId.GenerateNewId();
        var tempPatientObs = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Name = "Temp_Patient",
            Time = now,
            Value = 36.5
        };
        var tempIncubatorObs = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Name = "Temp_Incubator",
            Time = now.AddMinutes(-10), // 10 minutos antes
            Value = 37.0
        };

        var tempGradientObs = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Name = "Temp_Gradient",
            Time = now.AddSeconds(1),
            Value = 37.0
        };
        _observationServiceMock.Setup(s => s.FindAnyWithSameDate(patientId, now, "Temp_Gradient"))
            .ReturnsAsync([tempGradientObs]);

        _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([tempIncubatorObs]);

        _observationServiceMock.Setup(s => s.InsertObservation(
            It.IsAny<PatientObservation>(),
            It.IsAny<bool>(),
            It.IsAny<bool>()
        )).Callback<PatientObservation, bool, bool>((obs, _, _) =>
        {
            Action assertions = () =>
            {
                Assert.That(obs.Name, Is.EqualTo("Temp_Gradient"));
                Assert.That(Math.Abs((double)obs.Value - (37.0 - 36.5)), Is.LessThan(0.001));
            };
        });


        await _calculatedObservations.CalculateTempGradient(tempPatientObs);


        _observationServiceMock.Verify(s => s.InsertObservation(
            It.IsAny<PatientObservation>(),
            It.IsAny<bool>(),
            It.IsAny<bool>()
        ), Times.Once());
    }

    [Test]
    public async Task CalculateTempGradient_WhenOneTemperatureIsMissing_ShouldNotCalculateGradient()
    {
        var patientId = ObjectId.GenerateNewId();
        var tempPatientObs = new PatientObservation
        {
            PatientId = patientId,
            Name = "Temp_Patient",
            Time = DateTime.UtcNow,
            Value = 36.5
        };

        // Configuramos el mock para que no devuelva ninguna observación para Temp_Incubator
        _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);


        await _calculatedObservations.CalculateTempGradient(tempPatientObs);


        _observationServiceMock.Verify(s => s.InsertObservation(
            It.IsAny<PatientObservation>(),
            It.IsAny<bool>(),
            It.IsAny<bool>()
        ), Times.Never()); // Verificamos que InsertObservation no se llama
    }

    [Test]
    public async Task CalculateIntravenousLineObservation_ShouldCalculateObservationAndAdjustTimeIfNecessary()
    {
        var patientId = ObjectId.GenerateNewId();
        var currentTime = DateTime.UtcNow;
        var obs = new PatientObservation
        {
            PatientId = patientId,
            Name = "IntravenousLine",
            Value = new PatientIntravenousLinesValue(),
            Time = currentTime
        };

        _observationServiceMock.Setup(s => s.FindLastIntravenousLinesObservationByLocation(patientId))
            .ReturnsAsync([]);

        PatientObservation? insertedObservation = null;
        _observationServiceMock.Setup(s =>
                s.InsertObservation(It.IsAny<PatientObservation>(), It.IsAny<bool>(), It.IsAny<bool>()))
            .Callback<PatientObservation, bool, bool>((ob, _, _) => insertedObservation = ob)
            .Returns(Task.CompletedTask);

        _observationServiceMock.Setup(s => s.FindLastObservations(It.IsAny<ObjectId>(), 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        await _calculatedObservations.CalculateIntravenousLineObservation(obs);

        Assert.That(insertedObservation, Is.Not.Null);
        Action assertions = () =>
        {
            Assert.That(insertedObservation!.PatientId, Is.EqualTo(patientId));
            Assert.That(insertedObservation.Name, Is.EqualTo("IntravenousLines"));
            Assert.That(insertedObservation.Time,
                Is.GreaterThanOrEqualTo(currentTime)); // Verificar que la hora no sea anterior a la hora actual
        };
    }

    [Test]
    public async Task CalculateMonitor_WithValidObservationOrTreatment_ShouldCalculateAndInsertObservation()
    {
        var patientId = ObjectId.GenerateNewId();
        var monitorObservation = new PatientObservation
        {
            PatientId = patientId
        };

        var activeObservation = new PatientObservation
        {
            Code = _optionsApiSettings.Value.RegionalBrainSaturation?.FirstOrDefault(),
            PatientId = patientId
        };

        var activeTreatment = new PatientTreatment
        {
            PatientId = patientId
        };


        _observationServiceMock.Setup(s =>
                s.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
            .ReturnsAsync([activeObservation]);

        _treatmentServiceMock.Setup(s => s.GetActiveTreatmentsByPatient(It.IsAny<ObjectId>()))
            .ReturnsAsync(new List<PatientTreatment> { activeTreatment });

        _observationServiceMock.Setup(s => s.InsertObservation(It.IsAny<PatientObservation>(), true, true))
            .Returns(Task.CompletedTask)
            .Verifiable();


        await _calculatedObservations.CalculateMonitor(monitorObservation);


        _observationServiceMock.Verify(s => s.InsertObservation(It.Is<PatientObservation>(o =>
                o.PatientId == patientId &&
                o.Name == "Monitor" &&
                o.CodingSystem == "ADAS" &&
                o.Min != null && Math.Abs(o.Min.Value - 0) < 0.01 &&
                o.Max != null && Math.Abs(o.Max.Value - 3) < 0.01
            ), It.IsAny<bool>(), It.IsAny<bool>()),
            Times.Once());
    }

    [Test]
    public async Task CalculateMonitor_WithPatientTreatment_ShouldCalculateAndInsertObservation()
    {
        // Arrange
        var patientId = ObjectId.GenerateNewId();
        var monitorTreatment = new PatientTreatment
        {
            PatientId = patientId
        };

        var activeTreatment = new PatientTreatment
        {
            PatientId = patientId
        };

        var patientObservation = new PatientObservation
        {
            Code = _optionsApiSettings.Value.Transcutaneous?.First(),
            PatientId = patientId,
            Expired = false
        };

        // Simular respuestas de los servicios
        _treatmentServiceMock.Setup(s => s.GetActiveTreatmentsByPatient(It.IsAny<ObjectId>()))
            .ReturnsAsync(new List<PatientTreatment> { activeTreatment });

        _observationServiceMock.Setup(s => s.InsertObservation(It.IsAny<PatientObservation>(), true, true))
            .Returns(Task.CompletedTask)
            .Verifiable();
        _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny<List<string>>()))
            .ReturnsAsync([patientObservation]);
        // Act
        await _calculatedObservations.CalculateMonitor(monitorTreatment);

        // Assert
        _observationServiceMock.Verify(s => s.InsertObservation(It.Is<PatientObservation>(o =>
                o.PatientId == patientId &&
                o.Name == "Monitor" &&
                o.CodingSystem == "ADAS" &&
                o.Min != null && Math.Abs(o.Min.Value - 0) < 0.01 &&
                o.Max != null && Math.Abs(o.Max.Value - 3) < 0.01
            ), It.IsAny<bool>(), It.IsAny<bool>()),
            Times.Once());
    }

    [Test]
    public async Task CalculateMonitor_WithIncompleteData_ShouldNotInsertObservation()
    {
        // Arrange
        var patientId = ObjectId.GenerateNewId();
        var incompleteObservation = new PatientObservation
        {
            PatientId = patientId
            // Proporcionar datos incompletos o irrelevantes
        };

        // Simular respuestas de los servicios
        _observationServiceMock.Setup(s =>
                s.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
            .ReturnsAsync([]);

        _observationServiceMock.Setup(s => s.InsertObservation(It.IsAny<PatientObservation>(), true, true))
            .Returns(Task.CompletedTask)
            .Verifiable();

        // Act
        await _calculatedObservations.CalculateMonitor(incompleteObservation);

        // Assert
        _observationServiceMock.Verify(
            s => s.InsertObservation(It.IsAny<PatientObservation>(), It.IsAny<bool>(), It.IsAny<bool>()),
            Times.Never());
    }

    [Test]
    public async Task CheckSurgeryExpired_WhenNotExpired_DoesNotInsertObservation()
    {
        var obs = new PatientObservation
        {
            Expired = false
        };

        await _calculatedObservations.CheckSurgeryExpired(obs);

        _observationServiceMock.Verify(s => s.InsertObservation(It.IsAny<PatientObservation>(), true, false),
            Times.Never);
    }

    [Test]
    public async Task CheckSurgeryExpired_WhenExpired_InsertsCorrectObservation()
    {
        var initialTime = DateTime.Now;
        var obs = new PatientObservation
        {
            Expired = true,
            PatientId = ObjectId.GenerateNewId(),
            Time = initialTime,
            Expires = 30
        };

        await _calculatedObservations.CheckSurgeryExpired(obs);

        _observationServiceMock.Verify(s => s.InsertObservation(It.Is<PatientObservation>(o =>
            o.PatientId == obs.PatientId &&
            o.Name == "Surgery" &&
            o.Min != null && Math.Abs(o.Min.Value - 0) < 0.01 &&
            o.Max != null && Math.Abs(o.Max.Value - 5) < 0.01 &&
            o.CodingSystem == "ADAS" &&
            o.Time == initialTime.AddSeconds(1) &&
            o.Value.Equals(0) && // Asegúrate de que la comparación de 'o.Value' sea apropiada para su tipo
            o.Expires == 30
        ), true, false), Times.Once);
    }

    [Test]
    public async Task CalculateComplexity_NewObservation_NoECMO_AddsComplexity()
    {
        var patientId = ObjectId.GenerateNewId();
        var patientTreatment = new PatientTreatment
        {
            Id = patientId
        };

        var patientObservation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Name = "Weight_Current",
            Value = 10
        };

        var complelxity = new PatientObservation
        {
            Id = patientId,
            Value = 1
        };

        // Mock de datos de tratamiento activo
        var activeTreatments = new List<PatientTreatment> { patientTreatment };
        _treatmentServiceMock.Setup(m => m.GetActiveTreatmentsByPatient(It.IsAny<ObjectId>()))
            .ReturnsAsync(activeTreatments);

        // Mock de datos de observación
        var observations = new List<PatientObservation> { patientObservation };
        _observationServiceMock.Setup(m => m.FindLastObservations(It.IsAny<ObjectId>(), 1, It.IsAny<List<string>>()))
            .ReturnsAsync(observations);

        var complexityObservations = new List<PatientObservation> { complelxity };
        _observationServiceMock.Setup(m => m.FindLastObservations(It.IsAny<ObjectId>(), 1, It.IsAny<List<string>>()))
            .ReturnsAsync(complexityObservations);

        var obs = patientObservation as BasePatientObservation;
        var result = await _calculatedObservations.CalculateComplexity(obs);


        // Verifica que el valor de complejidad calculado sea el esperado
        Assert.That(result.Name, Is.EqualTo("Weight_Current"));

        // Verifica que se hayan llamado los métodos esperados en los servicios mockeados
        _treatmentServiceMock.Verify(m => m.GetActiveTreatmentsByPatient(It.IsAny<ObjectId>()), Times.Once);

        _observationServiceMock.Verify(m => m.FindLastObservations(It.IsAny<ObjectId>(), 1, It.IsAny<List<string>>()),
            Times.Exactly(3));


        _observationServiceMock.Verify(s => s.InsertObservation(It.Is<PatientObservation>(o =>
            o.PatientId == obs.PatientId &&
            o.Name == "Complexity" &&
            o.CodingSystem == "ADAS" &&
            Equals(o.Value, 7)
        ), true, false), Times.Once);
    }

    [Test]
    public async Task CalculateComplexity_ExpiredObservation_DoesNotAddToComplexity()
    {
        // Configuración inicial
        var patientId = ObjectId.GenerateNewId();
        var expiredPatientObservation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Name = "Weight_Current",
            Value = 10,
            Expired = true // Observación expirada
        };

        var observations = new List<PatientObservation> { expiredPatientObservation };

        _observationServiceMock.Setup(m => m.FindLastObservations(It.IsAny<ObjectId>(), 1, It.IsAny<List<string>>()))
            .ReturnsAsync(observations);

        var obs = expiredPatientObservation as BasePatientObservation;
        var result = await _calculatedObservations.CalculateComplexity(obs);

        // Verificaciones
        Assert.That(result.Name, Is.EqualTo("Weight_Current"));

        _observationServiceMock.Verify(s => s.InsertObservation(It.Is<PatientObservation>(o =>
                o.PatientId == obs.PatientId &&
                o.Name == "Complexity" &&
                Equals(o.Value, 0) // Valor de complejidad no debe cambiar
        ), true, true), Times.Never); // No se debe llamar InsertObservation
    }

    [Test]
    public async Task CalculateComplexity_ECMOActive_AdjustsComplexity()
    {
        var code = new Code { Identifier = "705923009" };

        // Configuración inicial
        var patientId = ObjectId.GenerateNewId();
        var observation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Name = "ECMO",
            Value = 10
        };

        var lastObservation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Name = "Surgery",
            Value = 1
        };

        var patientTreatment = new PatientTreatment
        {
            Id = patientId
        };

        patientTreatment.RequestedGiveCodes.Add(code);

        // Mock de datos de tratamiento activo
        var activeTreatments = new List<PatientTreatment> { patientTreatment };
        _treatmentServiceMock.Setup(m => m.GetActiveTreatmentsByPatient(It.IsAny<ObjectId>()))
            .ReturnsAsync(activeTreatments);

        var observations = new List<PatientObservation> { lastObservation };

        _observationServiceMock.Setup(m => m.FindLastObservations(It.IsAny<ObjectId>(), 1, It.IsAny<List<string>>()))
            .ReturnsAsync(observations);

        BasePatientObservation obs = observation;
        var result = await _calculatedObservations.CalculateComplexity(obs);

        // Verificaciones
        Assert.That(result.Name, Is.EqualTo("ECMO"));

        _observationServiceMock.Verify(s => s.InsertObservation(It.Is<PatientObservation>(o =>
                o.PatientId == obs.PatientId &&
                o.Name == "ECMO" &&
                Equals(o.Value, 10) // Valor de complejidad no debe cambiar
        ), true, true), Times.Once);

        _observationServiceMock.Verify(s => s.InsertObservation(It.Is<PatientObservation>(o =>
            o.PatientId == obs.PatientId &&
            o.Name == "Complexity" &&
            Equals(o.Value, "1 ECMO")
        ), true, false), Times.Once);
    }

    [Test]
    public async Task CheckObsExistsAndIncrementTime_SameHourObservation_IncrementsTime()
    {
        // Configuración inicial
        var patientId = ObjectId.GenerateNewId();
        var initialTime = DateTime.UtcNow;
        var sameHourObservation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Time = initialTime,
            Name = "TestObservation"
        };

        var existingObservation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Time = initialTime, // Misma hora que sameHourObservation
            Name = "TestObservation"
        };

        // Mock del servicio de observación para que retorne una observación existente en la misma hora
        _observationServiceMock.Setup(m =>
                m.FindLastBeforeDate(It.IsAny<ObjectId>(), It.IsAny<DateTime>(), It.IsAny<string>()))
            .ReturnsAsync(existingObservation);

        var obs = sameHourObservation as BasePatientObservation;
        var result = await _calculatedObservations.CheckObsExistsAndIncrementTime(obs);

        // Verificaciones
        var resultObs = result as PatientObservation;
        Assert.That(resultObs, Is.Not.Null);
        Assert.That(resultObs!.Time, Is.GreaterThan(initialTime)); // Verifica que el tiempo ha sido incrementado
        Assert.That(resultObs.Time,
            Is.EqualTo(existingObservation.Time.AddSeconds(1))); // Verifica que el tiempo se incrementó en 1 segundo
    }


    [Test]
    public async Task CheckObsWithSameTimeExistsAndIncrementTime_WhenObservationWithSameTimeExists_IncrementsTime()
    {
        // Configuración inicial
        var patientId = ObjectId.GenerateNewId();
        var observationTime = DateTime.UtcNow;
        const string observationName = "TestObservation";

        var newObservation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Time = observationTime,
            Name = observationName
        };

        var existingObservation = new PatientObservation
        {
            Id = ObjectId.GenerateNewId(),
            PatientId = patientId,
            Time = observationTime, // Misma hora y nombre que newObservation
            Name = observationName
        };

        // Mock del servicio de observación para que retorne una observación existente con el mismo tiempo y nombre
        _observationServiceMock.Setup(m => m.FindAnyWithSameDate(patientId, observationTime, observationName))
            .ReturnsAsync([existingObservation]);

        BasePatientObservation obs = newObservation;
        var result = await _calculatedObservations.CheckObsWithSameTimeExistsAndIncrementTime(obs);

        // Verificaciones
        var resultObs = result as PatientObservation;
        Assert.That(resultObs, Is.Not.Null);
        using (Assert.EnterMultipleScope())
        {
            {
                Assert.That(resultObs!.Time,
                    Is.EqualTo(observationTime.AddSeconds(1))); // Verifica que el tiempo se haya incrementado en 1 segundo
                Assert.That(existingObservation.Id,
                    Is.Not.EqualTo(resultObs.Id)); // Verifica que el Id sea diferente al de la observación existente
            }
            ;
        }
    }

    [Test]
    public async Task CheckTreatmentMedicines_ProcessesTreatmentCorrectly_WithParentalNutritionMedicine()
    {
        var patientId = ObjectId.GenerateNewId();
        var code = new Code { Identifier = "705923009" };

        var medicationObs = new PatientObservation { PatientId = patientId, Value = 2 };

        // Configuración inicial
        var treatment = new PatientTreatment
        {
            PatientId = patientId,
            Notes =
            [
                new Note { Comment = "NPT", CommentType = "formularybaseformulation" }
            ],
            RequestedGiveCodes = [code],
            RequestedGiveTreatment = "Medicación"
        };

        var medicine = new Medicine { Codes = [code.Identifier] };

        var lastMedicationObs = new List<PatientObservation> { medicationObs };

        var expectedMedicines = new List<Medicine> { medicine };

        var activeTreatments = new List<PatientTreatment> { treatment };

        // Mock de medicineService para que devuelva medicinas esperadas          

        _medicineServiceMock.Setup(m => m.GetByCodeOrNote(It.IsAny<List<string>>()))
            .ReturnsAsync(expectedMedicines);

        _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny<List<PatientTreatment>>()))
            .ReturnsAsync(expectedMedicines);

        _treatmentServiceMock.Setup(m => m.GetActiveTreatmentsByPatient(It.IsAny<ObjectId>()))
            .ReturnsAsync(activeTreatments);

        _observationServiceMock
            .Setup(m => m.FindLastObservations(It.IsAny<ObjectId>(), 1, new List<string> { "Medication" }))
            .ReturnsAsync(lastMedicationObs);

        _observationServiceMock.Setup(s => s.FindLastObservations(It.IsAny<ObjectId>(), 1, It.IsAny<List<string>>()))
            .ReturnsAsync([]);
        // Otras configuraciones de mock según sea necesario

        // Llamada al método bajo prueba
        await _calculatedObservations.CheckTreatmentMedicines(treatment);

        // Verificaciones
        // Verifica que las llamadas a los servicios mockeados son como se esperan
        // Verifica que la lógica de procesamiento de medicamentos es correcta
        // Puedes usar Assert o Verify de Moq según corresponda
        // ...

        _observationServiceMock.Verify(s => s.InsertObservation(It.Is<PatientObservation>(o =>
            o.PatientId == patientId &&
            o.Name == "Medication" &&
            o.CodingSystem == "ADAS" &&
            Equals(o.Value, 1)
        ), true, false), Times.Once);
    }
}