using e_suite.API.Common.exceptions;
using e_suite.API.Common.models;
using e_suite.Database.Audit;
using e_suite.Database.Core.Tables.CustomFields;
using e_suite.Database.Core.Tables.Forms;
using eSuite.Core.CustomFields;
using eSuite.Core.Miscellaneous;
using Moq;
using NUnit.Framework;

namespace e_suite.Modules.FormsManagerUnitTests.FormsManagerUnitTests;

[TestFixture]
public class CreateFormInstancesAsyncUnitTests : FormsManagerUnitTestBase
{

    [SetUp]
    public async Task SetUp()
    {
        await base.Setup();
    }

    [Test]
    public Task CreateFormInstancesAsync_WhenTemplateDoesNotExist_ThrowsError()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserDisplayName = "Testy the tester",
            UserId = 726
        };

        var formInstance = new CreateFormInstance
        {
            TemplateId = new GeneralIdRef
            {
                Guid = new Guid("95dc0407-000a-4e11-891e-1a9c41e1a89a")
            }
        };

        //Assert
        var actualResult = Assert.ThrowsAsync<NotFoundException>(async () =>
        {
            //Act
            await _formManager.CreateFormInstancesAsync(auditUserDetails, [formInstance], CancellationToken.None);
        });

        Assert.That(actualResult.Message, Is.EqualTo("Unable to find template"));
        return Task.CompletedTask;
    }

    [Test]
    public Task CreateFormInstancesAsync_WhenTemplateVersionDoesNotExist_ThrowsError()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserDisplayName = "Testy the tester",
            UserId = 726
        };

        var template = new FormTemplate
        {
            Guid = new Guid("8602d300-a364-4124-8e73-3ad3a237abe6"),
            Id = 8472,
            Name = "My Template"
        };

        _fakeformRepository.FormTemplates.Add(template);

        var formInstance = new CreateFormInstance
        {
            TemplateId = new GeneralIdRef
            {
                Guid = template.Guid
            }
        };
        
        //Assert
        var actualResult = Assert.ThrowsAsync<NotFoundException>(async () =>
        {
            //Act
            await _formManager.CreateFormInstancesAsync(auditUserDetails, [formInstance], CancellationToken.None);
        });

        Assert.That(actualResult.Message, Is.EqualTo("Unable to find template version"));
        return Task.CompletedTask;
    }

    [Test]
    public async Task CreateFormInstancesAsync_WhenEverythingExists_CreatesFormInstance()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserDisplayName = "Testy the tester",
            UserId = 5618
        };

        var template = new FormTemplate
        {
            Guid = new Guid("8602d300-a364-4124-8e73-3ad3a237abe6"),
            Id = 8472,
            Name = "My Template"
        };

        var templateVersion = new FormTemplateVersion
        {
            Guid = new Guid("6d5e06d7-e8e4-4757-9795-41324b2501a8"),
            Id = 180,
            FormDefinition = "<p>The rules of acquisition...</p>",
            Version = 1, 
            Template = template,
            TemplateId = template.Id
        };

        template.Versions.Add(templateVersion);

        _fakeformRepository.FormTemplates.Add(template);
        _fakeformRepository.FormTemplateVersions.Add(templateVersion);

        var formInstance = new CreateFormInstance
        {
            TemplateId = new GeneralIdRef
            {
                Guid = template.Guid
            },
            Version = 1
        };
        
        //Act
        await _formManager.CreateFormInstancesAsync(auditUserDetails, [formInstance], CancellationToken.None);

        //Assert
        Assert.That( _fakeformRepository.FormInstances, Has.Count.EqualTo(1));
    }

    [Test]
    public async Task CreateFormInstancesAsync_WhenFormInstanceHasValues_ValuesAreSaved()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserDisplayName = "Testy the tester",
            UserId = 5618
        };

        var template = new FormTemplate
        {
            Guid = new Guid("8602d300-a364-4124-8e73-3ad3a237abe6"),
            Id = 8472,
            Name = "My Template"
        };

        var templateVersion = new FormTemplateVersion
        {
            Guid = new Guid("6d5e06d7-e8e4-4757-9795-41324b2501a8"),
            Id = 180,
            FormDefinition = "<p>The rules of acquisition...</p>",
            Version = 1,
            Template = template,
            TemplateId = template.Id
        };

        template.Versions.Add(templateVersion);

        _fakeformRepository.FormTemplates.Add(template);
        _fakeformRepository.FormTemplateVersions.Add(templateVersion);

        var formInstance = new CreateFormInstance
        {
            TemplateId = new GeneralIdRef
            {
                Guid = template.Guid
            },
            Version = 1,
            CustomFieldValues = new List<CustomFieldValues>
            {
                new()
                {
                    Id = new GeneralIdRef
                    {
                        Guid = new Guid("bf537a45-2d16-4cc4-9225-3c26e74d78a3")
                    },
                    Values = new List<CustomFieldValue>
                    {
                        new(){DisplayValue = "Hello", Value = "Hello"}
                    }
                }
            }
        };

        var customFieldValues = new List<ValidatedCustomFieldValue>();
        customFieldValues.Add(new()
        {
            CustomFieldId = 1,
            CustomField = new CustomField
            {
                Guid = new Guid("8d901bf5-6fc5-43ce-aa73-8034fdb6b38d"),
                Id = 1,
                FieldType = FieldType.Text
            },
            Index = 0,
            Value = "Hello",
            DisplayValue = "Hello"
        });

        var validatedFieldsResult = Task.FromResult(customFieldValues.AsEnumerable());

        customFieldValidatorMock
            .Setup(x => x.ValidateFields(It.IsAny<AuditUserDetails>(), It.IsAny<IEnumerable<CustomFieldValues>>(),
                It.IsAny<IReadOnlyCollection<CustomField>>(), It.IsAny<CancellationToken>()))
            .Returns(validatedFieldsResult);


        //Act
        await _formManager.CreateFormInstancesAsync(auditUserDetails, [formInstance], CancellationToken.None);

        //Assert
        Assert.That(_fakeformRepository.FormInstances, Has.Count.EqualTo(1));
        Assert.That(_fakeformRepository.FormFieldValues, Has.Count.EqualTo(1));
    }
}