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 Options = Microsoft.Extensions.Options.Options;

namespace adas_core.Test.Repositories;

[TestFixture]
[Category("Integration")]
public class MedicineRepositoryTest
{
    [OneTimeSetUp]
    public async Task Init()
    {
        _optionsApiSettings = Options.Create(_apiSettings);

        _testMedicine = new Medicine
        {
            Id = ObjectId.GenerateNewId(),
            Codes = ["12345"],
            Notes = ["note1"],
            Name = "test",
            Group = [MedicineEnum.Group.Metabolic.ToString()]
        };

        await IntegrationDb.Database.DropCollectionAsync("medicines");
        await IntegrationDb.Database.CreateCollectionAsync("medicines");

        _repository = new MedicineRepository(_optionsApiSettings, IntegrationDb.Database);

        await _repository.InsertOneAsync(_testMedicine);

        var result = _repository.GetMedicineByCodeOrNote(["12345"]);

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

    private MedicineRepository _repository = null!;

    private readonly ApiSettings _apiSettings = new()
    {
        Medicines = "medicines"
    };

    private Medicine _testMedicine = null!;

    private IOptions<ApiSettings> _optionsApiSettings = null!;

    [Test]
    public async Task Get_Medicines_Of_Treatments_Return_Empty_List()
    {
        var result = await _repository.GetMedicineByCodeOrNote([""]);

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

    [Test]
    public async Task Get_Medicines_Of_Treatments_By_Code_When_Have_Code_And_Notes_Return_Paracetamol()
    {
        var id = ObjectId.GenerateNewId();
        var paracetamolMedicine = new Medicine
        {
            Id = id,
            Codes = ["322236009", "322246006", "370151002", "605677", "605779"],
            Type = ["ParacetamolOpiates"],
            Name = "Paracetamol"
        };

        await _repository.InsertOneAsync(paracetamolMedicine);

        var result = await _repository.GetMedicineByCodeOrNote([
            "Medicación", "Formulary Drug Intake", "1.12 kg", "605677"
        ]);
        using (Assert.EnterMultipleScope())
        {
            Assert.That(result, Is.Not.Null);
            Assert.That(id, Is.EqualTo(result.First().Id));
        };
        Assert.That(result, Has.Count.EqualTo(1));
    }

    [Test]
    public async Task GetMedicine_Find_Code_Return_Medicine()
    {
        var result = await _repository.GetMedicine("12345");

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

    [Test]
    public async Task GetMedicine_Not_Find_Code_Return_Empty()
    {
        var result = await _repository.GetMedicine("123456");

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

    [Test]
    public async Task GetMedicine_Find_Note_Return_Medicine()
    {
        var result = await _repository.GetMedicine("note1");

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

    [Test]
    public async Task UpdateMedicine_Return_Medicine()
    {
        var updateMedicine = new Medicine
        {
            Id = _testMedicine.Id,
            Codes = ["12345"],
            Notes = ["note1", "note2", "note3"],
            Name = "test",
            Group = [MedicineEnum.Group.Metabolic.ToString()]
        };

        var result = await _repository.UpdateMedicine(updateMedicine);
        var resultUpdate = await _repository.GetMedicineById(_testMedicine.Id);
        using (Assert.EnterMultipleScope())
        {
            
            Assert.That(result, Is.Not.Null);
            Assert.That(resultUpdate, Is.Not.Null);
            Assert.That(resultUpdate?.Notes != null && resultUpdate.Notes.Contains("note3"), Is.True);
        };
    }
}