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 MongoDB.Bson;
using MongoDB.Driver;
using Serilog;
using static adas_core.Domain.Models.MongoModels.Section;
using Options = Microsoft.Extensions.Options.Options;

namespace adas_core.Test.Repositories;

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

        var boxes = new List<Box>
        {
            new() { Bed = "bed1", IsActive = true },
            new() { Bed = "bed2", IsActive = true },
            new() { Bed = "bed3", IsActive = true },
            new() { Bed = "bed4", IsActive = true },
            new() { Bed = "bed5", IsActive = true },
            new() { Bed = "bed6", IsActive = true }
        };

        var section1 = new Section
        {
            _id = SectionId1,
            Id = "UCIP1",
            SectionTitle = "UCI PEDIÁTRICA 1",
            PointOfCare = "UCIP1",
            Items =
            [
                new SectionItem
                {
                    Group = "Pasillo 1",
                    Boxes = boxes
                }
            ]
        };

        var section2 = new Section
        {
            _id = SectionId2,
            Id = "UCIP2",
            SectionTitle = "UCI PEDIÁTRICA 2",
            PointOfCare = "UCIP2",
            Items =
            [
                new SectionItem
                {
                    Group = "Pasillo 1",
                    Boxes = boxes
                }
            ]
        };

        //await IntegrationDb.Database.DropCollectionAsync("config_sections");
        await IntegrationDb.Database.CreateCollectionAsync("config_sections");

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

        await _repository.InsertOneAsync(section1);
        await _repository.InsertOneAsync(section2);
    }

    private SectionRepository _repository;

    private readonly ApiSettings _apiSettings = new()
    {
        ConfigSections = "config_sections"
    };

    private IOptions<ApiSettings> _optionsApiSettings;

    private static readonly ObjectId SectionId1 = ObjectId.GenerateNewId();
    private static readonly ObjectId SectionId2 = ObjectId.GenerateNewId();

    [Test]
    public async Task GetAll_Return_List_Sections()
    {
        var result = await _repository.GetAll();

        Assert.That(result, Is.Not.Null);
        Assert.That(result, Has.Count.EqualTo(2));
    }

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

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

    [Test]
    public async Task FindBySection_Find_Return_Section()
    {
        var result = await _repository.FindBySection("UCI PEDIÁTRICA 2");

        Assert.That(result, Is.Not.Null);
        Assert.That(result!.SectionTitle, Is.EqualTo("UCI PEDIÁTRICA 2"));
    }

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

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

    [Test]
    public async Task FindByPointOfCare_Find_Return_Section()
    {
        var result = await _repository.FindByPointOfCare("UCIP1");

        Assert.That(result, Is.Not.Null);
        Assert.That(result!.SectionTitle, Is.EqualTo("UCI PEDIÁTRICA 1"));
    }

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

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

    [Test]
    public async Task FindById_Find_Return_Section()
    {
        var result = await _repository.FindById("UCIP1");

        Assert.That(result, Is.Not.Null);
        Assert.That(result!.SectionTitle, Is.EqualTo("UCI PEDIÁTRICA 1"));
    }

    [Test]
    public async Task FindById_Not_Find_Id_Return_null()
    {
        var result = await _repository.FindById(ObjectId.GenerateNewId());

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

    [Test]
    public async Task FindById_Find_Id_Return_Section()
    {
        var result = await _repository.FindById(SectionId2);

        Assert.That(result, Is.Not.Null);
        Assert.That(result!.SectionTitle, Is.EqualTo("UCI PEDIÁTRICA 2"));
    }

    [Test]
    public async Task FindByLocation_Not_Find_Return_Emty_List()
    {
        PatientLocation location = new("UCIP3", "bed1");
        var result = await _repository.FindByLocation(location);

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

    [Test]
    public async Task FindByLocation_Find_Return_List()
    {
        PatientLocation location = new("UCIP1", "bed1");
        var result = await _repository.FindByLocation(location);

        Assert.That(result, Is.Not.Null);
        Assert.That(result, Has.Count.EqualTo(1));
        Assert.That(result[0].SectionTitle, Is.EqualTo("UCI PEDIÁTRICA 1"));
    }


    [Test]
    public async Task InsertUpdateAndDeleteSection()
    {
        var updateId = ObjectId.GenerateNewId();

        var boxes = new List<Box>
        {
            new() { Bed = "bed1", IsActive = true },
            new() { Bed = "bed2", IsActive = true },
            new() { Bed = "bed3", IsActive = true },
            new() { Bed = "bed4", IsActive = true },
            new() { Bed = "bed5", IsActive = true },
            new() { Bed = "bed6", IsActive = true }
        };

        var section1 = new Section
        {
            _id = ObjectId.GenerateNewId(),
            Id = "UCIP_U_Id",
            SectionTitle = "UCI PEDIÁTRICA U",
            PointOfCare = "UCIP_U",
            Items =
            [
                new SectionItem
                {
                    Group = "Pasillo 1",
                    Boxes = boxes
                }
            ]
        };

        var sectionUpdate = new Section
        {
            _id = updateId,
            Id = "UCIP_U_Id",
            SectionTitle = "UCI PEDIÁTRICA UPDATE",
            PointOfCare = "UCIP_U",
            Items =
            [
                new SectionItem
                {
                    Group = "Pasillo 1",
                    Boxes = boxes
                }
            ]
        };


        await _repository.InsertOneAsync(section1);
        try
        {
            await _repository.Collection.CountDocumentsAsync(_ => true);
        }
        catch (Exception ex)
        {
            Log.Debug(ex.ToString());
            throw;
        }

        var resultInsert = await _repository.FindById("UCIP_U_Id");

        Assert.That(resultInsert, Is.Not.Null);
        Assert.That(resultInsert.SectionTitle, Is.EqualTo("UCI PEDIÁTRICA U"));

        var result = await _repository.UpdateSection(sectionUpdate);

        Assert.That(result, Is.Not.Null);
        Assert.That(result.SectionTitle, Is.Not.EqualTo("UCI PEDIÁTRICA U"));
        Assert.That(result.SectionTitle, Is.EqualTo("UCI PEDIÁTRICA UPDATE"));

        await _repository.Collection.DeleteOneAsync(s => s.Id == "UCIP_U_Id");

        var resultDelete = await _repository.FindById("UCIP_U_Id");

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