using e_suite.API.Common.exceptions;
using e_suite.API.Common.models;
using eSuite.Core.Miscellaneous;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;

namespace eSuite.API.UnitTests.Controllers.FormsControllerUnitTests;

[TestFixture]
public class GetFormTemplateUnitTests : FormsControllerTestBase
{
    [SetUp]
    public override async Task Setup()
    {
        await base.Setup();
    }

    [Test]
    public async Task GetFormTemplate_ByGuidOnly_ReturnsOk()
    {
        //Arrange
        var formGuid = new Guid("c396663c-63ae-464b-9bd4-c5c90abf2b26");
        var formDefinition = "TestDef";
        var formName = "TestName";
        long id = 1;
        var idRef = new GeneralIdRef
        {
            Guid = formGuid,
            Id = null
        };

        var formObj = new GetFormTemplate
        {
            Definition = formDefinition,
            Name = formName,
            Id = id,
            Guid = formGuid,
            Version = 1
        };
        _formsManagerMock!.Setup(x => x.GetFormTemplateAsync(It.Is<GeneralIdRef>(f => f.Id == null && f.Guid == formGuid), It.IsAny<CancellationToken>())).ReturnsAsync(formObj);

        //Act
        var res = await _formsController.GetFormTemplate(idRef);

        //Assert
        var objectResult = res as OkObjectResult;
        Assert.That(objectResult?.Value, Is.Not.Null);
        if (objectResult?.Value is not null)
        {
            Assert.That(objectResult.Value.GetType(), Is.EqualTo(typeof(GetFormTemplate)));
            var form = objectResult?.Value as GetFormTemplate;
            Assert.That(form?.Name, Is.EqualTo(formName));
            Assert.That(form?.Definition, Is.EqualTo(formDefinition));
            Assert.That(form?.Guid, Is.EqualTo(formGuid));
            Assert.That(form?.Id, Is.EqualTo(id));
        }
    }

    [Test]
    public async Task GetFormTemplate_ByIdOnly_ReturnsOK()
    {
        //Arrange
        var formGuid = new Guid("20d67e19-7551-4ebc-93f1-5f6d4df1dea8");
        var formDefinition = "TestDef";
        var formName = "TestName";
        long id = 1;
        var idRef = new GeneralIdRef
        {
            Guid = null,
            Id = id
        };

        var formObj = new GetFormTemplate
        {
            Definition = formDefinition,
            Name = formName,
            Id = id,
            Guid = formGuid,
            Version = 1
        };
        _formsManagerMock!.Setup(x => x.GetFormTemplateAsync(It.Is<GeneralIdRef>(f => f.Id == id && f.Guid == null), It.IsAny<CancellationToken>())).ReturnsAsync(formObj);

        //Act
        var res = await _formsController.GetFormTemplate(idRef);

        //Assert
        var objectResult = res as OkObjectResult;
        Assert.That(objectResult?.Value, Is.Not.Null);
        if (objectResult?.Value is not null)
        {
            Assert.That(objectResult.Value.GetType(), Is.EqualTo(typeof(GetFormTemplate)));
            var form = objectResult?.Value as GetFormTemplate;
            Assert.That(form?.Name, Is.EqualTo(formName));
            Assert.That(form?.Definition, Is.EqualTo(formDefinition));
            Assert.That(form?.Guid, Is.EqualTo(formGuid));
            Assert.That(form?.Id, Is.EqualTo(id));
        }
    }

    [Test]
    public void GetFormTemplate_UnexistingId_Returns404()
    {
        //Arrange
        long id = 1;
        const string errorMessage = "Guid error";
        var idRef = new GeneralIdRef
        {
            Guid = null,
            Id = id
        };
        _formsManagerMock?.Setup(x => x.GetFormTemplateAsync(It.IsAny<GeneralIdRef>(), It.IsAny<CancellationToken>())).ThrowsAsync(new NotFoundException(errorMessage));

        //Assert
        Assert.ThrowsAsync<NotFoundException>(async () =>
        {
            //Act
            var res = await _formsController.GetFormTemplate(idRef);
        });
    }
}