using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Repositories;
using Microsoft.Extensions.Options;
using Options = Microsoft.Extensions.Options.Options;

namespace adas_core.Test.Repositories;

[TestFixture]
[Category("Integration")]
public class PatientArchiveRepositoryTest
{
    /// <summary>
    /// Performs one-time setup for integration tests by seeding the patient archive collection
    /// with three predefined <see cref="Patient"/> records after resetting the collection.
    /// </summary>
    [OneTimeSetUp]
        public async Task Init()
        {
            _optionsApiSettings = Options.Create(_apiSettings);
    
            var patient1 = new Patient
            {
                UnitString = "PointOfCare",
                Bed = "bed1",
                PatientNumber = "patientNumber1",
                Person = new Person
                {
                    FirstName = "firstName1",
                    LastName = "lastName1",
                    BirthDate = new DateTime(),
                    Gender = PatientEnum.Gender.Male
                }
            };
    
            var patient2 = new Patient
            {
                UnitString = "PointOfCare",
                Bed = "bed2",
                PatientNumber = "patientNumber2",
                Person = new Person
                {
                    FirstName = "firstName2",
                    LastName = "lastName2",
                    BirthDate = new DateTime(),
                    Gender = PatientEnum.Gender.Male
                }
            };
    
            var patient3 = new Patient
            {
                UnitString = "PointOfCare",
                Bed = "bed3",
                PatientNumber = "patientNumber3",
                Person = new Person
                {
                    FirstName = "firstName3",
                    LastName = "lastName3",
                    BirthDate = new DateTime(),
                    Gender = PatientEnum.Gender.Male
                }
            };
    
            await IntegrationDb.Database.DropCollectionAsync("archive_patient");
            await IntegrationDb.Database.CreateCollectionAsync("archive_patient");
    
            _repository = new PatientArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
    
            await _repository.InsertOneAsync(patient1);
            await _repository.InsertOneAsync(patient2);
            await _repository.InsertOneAsync(patient3);
        }

    private PatientArchiveRepository _repository;

    private readonly ApiSettings _apiSettings = new()
    {
        ArchivePatientsDiagnosis = "archive_patients"
    };

    private IOptions<ApiSettings> _optionsApiSettings;

    /// <summary>
    /// Verifies that the FindByPatientNumber repository method returns null when no record is found for the provided patient number.
    /// </summary>
    [Test]
        public async Task FindByPatientNumber_Not_Find_Return_null()
        {
            var result = await _repository.FindByPatientNumber("");
    
            Assert.That(result, Is.Null);
        }

    /// <summary>
    /// Verifies that the repository's FindByPatientNumber method successfully retrieves a patient
    /// matching the provided patient number, ensuring the returned patient is not null and has
    /// the expected PatientNumber.
    /// </summary>
    [Test]
        public async Task FindByPatientNumber_Find_Return_Patient()
        {
            var result = await _repository.FindByPatientNumber("patientNumber1");
    
            Assert.That(result, Is.Not.Null);
            Assert.That(result.PatientNumber, Is.EqualTo("patientNumber1"));
        }

    /// <summary>
    /// Verifies that the repository's <c>FindAll</c> method returns a non-null list containing the expected number of patient records.
    /// </summary>
    [Test]
        public async Task FindAll_Return_List_Patients()
        {
            var result = await _repository.FindAll();
    
            Assert.That(result, Is.Not.Null);
            Assert.That(result.Count, Is.EqualTo(3));
        }
}