using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using adas_core.Infrastructure.Repositories;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using Options = Microsoft.Extensions.Options.Options;

namespace adas_core.Test.Repositories;

[TestFixture]
[Category("Integration")]
public class TreatmentArchiveRepositoryTest
{
    /// <summary>
    /// One-time setup method that prepares the integration test environment for the treatment archive repository by creating and inserting two sample patient treatments (one new and one discontinued) into a freshly created archive collection.
    /// </summary>
    [OneTimeSetUp]
        public async Task Init()
        {
            _optionsApiSettings = Options.Create(_apiSettings);
    
            var treatment1 = new PatientTreatment
            {
                Id = ObjectId.GenerateNewId(),
                PatientId = PatientId,
                OrderControl = OrderControlType.Nw,
                PlacerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
                FillerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
                OrderStatus = "A",
                OrderTime = DateTime.Now,
                Notes = [],
                Routes = []
            };
    
            var treatment2 = new PatientTreatment
            {
                Id = ObjectId.GenerateNewId(),
                PatientId = PatientId,
                OrderControl = OrderControlType.Dc,
                PlacerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
                FillerOrder = new Entity { EntityIdentifier = "3690", NamespaceId = "CareVue" },
                OrderStatus = "A",
                OrderTime = DateTime.Now.AddDays(-5),
                Notes = [],
                Routes = []
            };
    
            await IntegrationDb.Database.DropCollectionAsync("archive_patients_treatments");
            await IntegrationDb.Database.CreateCollectionAsync("archive_patients_treatments");
    
            _repository = new TreatmentArchiveRepository(_optionsApiSettings, IntegrationDb.Database);
    
            await _repository.InsertOneAsync(treatment1);
            await _repository.InsertOneAsync(treatment2);
    
            Assert.That(_repository.Collection.FindAsync(_ => true).Result.ToList(), Has.Count.EqualTo(2));
        }

    private TreatmentArchiveRepository _repository;

    private readonly ApiSettings _apiSettings = new()
    {
        ArchivePatientsTreatments = "archive_patients_treatments"
    };

    private IOptions<ApiSettings> _optionsApiSettings;

    private static readonly DateTime Now = DateTime.Now;
    private static readonly ObjectId PatientId = ObjectId.GenerateNewId();


    /// <summary>
    /// Tests the <see cref="DeleteBeforeDate"/> repository method to ensure it correctly removes records older than the specified cutoff date,
    /// leaving only the most recent record. Verifies that when multiple patient records exist, deletion by date retains exactly one record.
    /// </summary>
    [Test]
        public async Task DeleteBeforeDate()
        {
            var result = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
    
            Assert.That(result, Is.Not.Null);
            Assert.That(result.ToList(), Has.Count.GreaterThan(1));
    
            await _repository.DeleteBeforeDate(Now.AddHours(-2));
    
            var resultDelete = await _repository.Collection.FindAsync(p => p.PatientId == PatientId);
    
            Assert.That(resultDelete, Is.Not.Null);
            Assert.That(resultDelete.ToList(), Has.Count.EqualTo(1));
        }

    /// <summary>
    /// Verifies that the repository successfully retrieves a non-empty collection of records associated with the specified patient.
    /// </summary>
    [Test]
        public async Task FindAllFromPatient()
        {
            var result = await _repository.FindAllFromPatient(PatientId);
    
            Assert.That(result, Is.Not.Null);
            Assert.That(result.ToList(), Has.Count.GreaterThan(0));
        }
}