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

namespace adas_core.Test.Utilities;

/// <summary>
/// Provides a collection of utility members to support testing operations and helper functionality.
/// </summary>
public class TestUtilities
{
    /// <summary>
    /// Creates and returns a fully populated, valid <see cref="PointOfCare"/> instance with predefined test values, typically used as a helper for unit testing or seeding sample data.
    /// </summary>
    /// <returns>A new <see cref="PointOfCare"/> object initialized with valid identifiers, room and bed information, an available status, a default configuration, and a referenced unit.</returns>
    public static PointOfCare CreateValidPointOfCare()
        {
            return new PointOfCare
            {
                Id = ObjectId.GenerateNewId(),
                Room = "Test Room",
                Bed = "Test Bed",
                UnitId = ObjectId.GenerateNewId(),
                Configuration = new PointOfCareConfiguration(),
                Status = StatusEnum.PointOfCare.Available,
                AdmissionId = ObjectId.GenerateNewId(),
                Unit = CreateValidUnit(),
                UnitName = "Test Unit"
            };
        }

    /// <summary>
    /// Creates a valid <see cref="Discharge"/> instance populated with generated identifiers, current UTC timestamps, and default test values for use in test scenarios.
    /// </summary>
    /// <returns>A fully populated <see cref="Discharge"/> object with all required fields set to valid values.</returns>
    public static Discharge CreateValidDischarge()
        {
            return new Discharge
            {
                Id = ObjectId.GenerateNewId(),
                PointOfCareId = ObjectId.GenerateNewId(),
                UnitId = ObjectId.GenerateNewId(),
                DischargeDate = DateTime.UtcNow,
                PatientId = ObjectId.GenerateNewId(),
                Destination = "Test Destination",
                DestinationOption = CreateValidOptionList(),
                ServiceOption = CreateValidOptionList(),
                Service = "Test Service",
                MedicalDischarge = DateTime.UtcNow,
                AdminDischarge = DateTime.UtcNow,
                NurseDischarge = DateTime.UtcNow
            };
        }

    /// <summary>
    /// Creates and returns a new <see cref="Patient"/> instance populated with valid test/default values, including a generated identifier, sample patient numbers, admission timestamp, and related option list entries for discharge status, altable, and origin.
    /// </summary>
    /// <returns>A fully initialized <see cref="Patient"/> object suitable for use in testing or seeding scenarios.</returns>
    public static Patient CreateValidPatient()
        {
            return new Patient
            {
                Id = ObjectId.GenerateNewId(),
                PatientNumber = "TestPatientNumber",
                PatientId = "TestPatientId",
                AdmTime = DateTime.UtcNow,
                DischargeStatus = new OptionList
                {
                    OptionType = "TestDischargeStatus",
                    Name = "TestDischargeStatusName",
                    IconDefault = "TestIcon",
                    Color = "TestColor",
                    Description = "TestDescription",
                    InitDate = DateTime.UtcNow,
                    EndDate = DateTime.UtcNow.AddDays(7) // Example end date
                },
                Altable = new OptionList
                {
                    OptionType = "TestAltable",
                    Name = "TestAltableName",
                    IconDefault = "TestAltableIcon",
                    Color = "TestAltableColor",
                    Description = "TestAltableDescription",
                    InitDate = DateTime.UtcNow,
                    EndDate = DateTime.UtcNow.AddDays(7) // Example end date
                },
                Origin = new OptionList
                {
                    OptionType = "TestOrigin",
                    Name = "TestOriginName",
                    IconDefault = "TestOriginIcon",
                    Color = "TestOriginColor",
                    Description = "TestOriginDescription",
                    InitDate = DateTime.UtcNow,
                    EndDate = DateTime.UtcNow.AddDays(7) // Example end date
                }
                // Initialize other properties as needed
            };
        }

    /// <summary>
    /// Creates a new <see cref="OptionList"/> instance populated with predefined valid test values, typically used as a helper for unit tests or test data seeding.
    /// </summary>
    /// <returns>An <see cref="OptionList"/> with sample values, where <c>InitDate</c> is set to the current UTC time and <c>EndDate</c> is set to one day after the current UTC time.</returns>
    public static OptionList CreateValidOptionList()
        {
            return new OptionList
            {
                OptionType = "Test Option",
                Name = "Test Name",
                IconDefault = "Test Icon",
                Color = "Test Color",
                Description = "Test Description",
                InitDate = DateTime.UtcNow,
                EndDate = DateTime.UtcNow.AddDays(1)
            };
        }

    /// <summary>
    /// Creates a valid <see cref="PatientLocation"/> instance populated with default test data for use in test scenarios.
    /// </summary>
    /// <returns>A <see cref="PatientLocation"/> with predefined unit name, bed, and room values.</returns>
    private static PatientLocation CreateValidPatientLocation()
        {
            return new PatientLocation
            {
                UnitName = "Test Unit",
                Bed = "Test Bed",
                Room = "Test Room"
            };
        }

    /// <summary>
    /// Creates a new <see cref="Unit"/> instance populated with valid default values, typically used for testing or seeding purposes.
    /// </summary>
    /// <returns>A new <see cref="Unit"/> object with a generated unique identifier, default title and name, no last update timestamp, an empty list of point of care IDs, an OK status, and a configuration with auto ADT enabled.</returns>
    public static Unit CreateValidUnit()
        {
            return new Unit
            {
                Id = ObjectId.GenerateNewId(),
                Title = "Test Unit",
                Name = "Test Unit",
                LastUpdate = null,
                PointOfCareIds = [],
                Status = StatusEnum.Type.Ok,
                Configuration = new UnitConfiguration
                {
                    AutoAdt = true,
                }
            };
        }

    /// <summary>
    /// Creates and returns a valid <see cref="Admission"/> instance populated with sample test data, including generated unique identifiers, a test person, option lists for origin, diagnosis, insulation, language barrier, allergies, and a patient location.
    /// </summary>
    /// <returns>A new <see cref="Admission"/> object fully initialized with valid test values.</returns>
    public static Admission CreateValidAdmission()
        {
            return new Admission
            {
                //Id = ObjectId.GenerateNewId(),
                AdmissionDate = DateTime.UtcNow,
                Nhc = ObjectId.GenerateNewId().ToString(),
                UnitId = ObjectId.GenerateNewId(),
                PointOfCareId = ObjectId.GenerateNewId(),
                Person = new Person
                {
                    FirstName = "Test First Name",
                    LastName = "Test Last Name"
                    // Initialize other properties as needed
                },
                Origin = CreateValidOptionList(),
                OriginAux = "Test Origin Aux",
                Diagnosis = CreateValidOptionList(),
                DiagnosisAux = "Test Diagnosis Aux",
                Allergies =
                [
                    CreateValidOptionList(),
                    CreateValidOptionList()
                    // Add more allergies as needed
                ],
                Insulation = CreateValidOptionList(),
                LanguageBarrier = [CreateValidOptionList()],
                PatientLocation = CreateValidPatientLocation()
                // Initialize other properties as needed
            };
        }

    /// <summary>
    /// Creates a valid <see cref="CardConfig"/> instance with a default structure consisting of a single row containing one <see cref="DisplayConfigEnums.CellType.DemographicCell"/> wrapped in a <see cref="DisplayConfigEnums.CellType.CellWrapper"/> with a grow priority of 1.
    /// </summary>
    /// <param name="id">The optional identifier for the configuration. If <c>null</c>, a new <see cref="ObjectId"/> is generated.</param>
    /// <returns>A newly created <see cref="CardConfig"/> populated with the default valid configuration.</returns>
    public static CardConfig CreateValidCardConfig(ObjectId? id = null)
        {
            return new CardConfig
            {
                Id = id ?? ObjectId.GenerateNewId(),
                Rows = new List<RowCardConfig>
                {
                    new()
                    {
                        Cells = new List<Cell>
                        {
                            new() { Type = DisplayConfigEnums.CellType.DemographicCell }
                        },
                        GrowPriority = 1,
                        Type = DisplayConfigEnums.CellType.CellWrapper
                    }
                }
            };
        }

    /// <summary>
    /// Creates a valid <see cref="CardDetailsConfig"/> instance configured for the nurse display, including a demographic row containing allergy and demographic cells. If no identifier is supplied, a new <see cref="ObjectId"/> is generated.
    /// </summary>
    /// <param name="id">The optional identifier to assign to the configuration. When <c>null</c>, a new <see cref="ObjectId"/> is generated.</param>
    /// <returns>A <see cref="CardDetailsConfig"/> populated with the nurse display configuration.</returns>
    public static CardDetailsConfig CreateValidCardDetailsNurseConfig(ObjectId? id = null)
        {
            return new CardDetailsConfig
            {
                Id = id ?? ObjectId.GenerateNewId(),
                NurseRows = new List<RowDetailsConfig>
                {
                    new()
                    {
                        Type = DisplayConfigEnums.RowType.Demographic,
                        Title = "Title details",
                        Cells = new List<CellDetails>
                        {
                            new()
                            {
                                Type = DisplayConfigEnums.CellType.CellWrapper,
                                Cells = new List<CellDetails>
                                {
                                    new()
                                    {
                                        Type = DisplayConfigEnums.CellType.AllergyCell
                                    },
                                    new()
                                    {
                                        Type = DisplayConfigEnums.CellType.DemographicCell
                                    }
                                }
                            }
                        }
                    }
                }
            };
        }

    /// <summary>
    /// Creates a valid <see cref="CardDetailsConfig"/> instance populated with a default smart section layout, including a general row that contains beacon color and isolation observations. If no identifier is supplied, a new <see cref="ObjectId"/> is generated for the configuration.
    /// </summary>
    /// <param name="id">The optional identifier to assign to the configuration. When <c>null</c>, a new <see cref="ObjectId"/> is generated.</param>
    /// <returns>A <see cref="CardDetailsConfig"/> configured with a predefined smart section layout.</returns>
    public static CardDetailsConfig CreateValidCardDetailsSmartConfig(ObjectId? id = null)
        {
            return new CardDetailsConfig
            {
                Id = id ?? ObjectId.GenerateNewId(),
                SmartSections = new List<SectionBoxLayout>
                {
                    new()
                    {
                        Type = DisplayConfigEnums.RowType.General,
                        Name = "Title details",
                        Rows = new List<RowBoxLayout>
                        {
                            new()
                            {
                                Type = DisplayConfigEnums.CellType.CellWrapper,
                                Observations = new List<ObservationRowBoxLayout>
                                {
                                    new()
                                    {
                                        Type = DisplayConfigEnums.CellType.BeaconColor
                                    },
                                    new()
                                    {
                                        Type = DisplayConfigEnums.CellType.Isolation
                                    }
                                }
                            }
                        }
                    }
                }
            };
        }

    /// <summary>
    /// Creates a valid <see cref="DisplayConfig"/> instance, generating new <see cref="ObjectId"/> values for any ID parameters that are <c>null</c>. Intended for use in test scenarios.
    /// </summary>
    /// <param name="type">The display type to assign to the configuration.</param>
    /// <param name="id">The optional identifier for the display config. A new <see cref="ObjectId"/> is generated when <c>null</c>.</param>
    /// <param name="idCard">The optional card config identifier. A new <see cref="ObjectId"/> is generated when <c>null</c>.</param>
    /// <param name="idDetail">The optional detail config identifier. A new <see cref="ObjectId"/> is generated when <c>null</c>.</param>
    /// <returns>A fully populated <see cref="DisplayConfig"/> with default field and hospital values.</returns>
    public static DisplayConfig CreateValidDisplayConfig(DisplayConfigEnums.DisplayType type, ObjectId? id,
            ObjectId? idCard, ObjectId? idDetail)
        {
            return new DisplayConfig
            {
                Id = id ?? ObjectId.GenerateNewId(),
                CardConfigId = idCard ?? ObjectId.GenerateNewId(),
                DetailConfigId = idDetail ?? ObjectId.GenerateNewId(),
                Type = type,
                FieldList = new List<Field> { new() { Name = "FR", Last = 2 } },
                Hospital = "Test Hospital"
            };
        }
}