using System.Net;
using FluentAssertions;
using IWS5.Autotest.IWS5.Api.Api;
using IWS5.Autotest.IWS5.Api.Common;
using IWS5.Core.DTO;
using IWS5.Core.Models;
using IWS5.Core.Models.Request;
using Newtonsoft.Json;
using NUnit.Framework.Internal;

namespace IWS5.Autotest.IWS5.Autotests
{
    public class DocumentControllerApiTest
    {
        //check test data
        //todo when the startup will generate a data then rewrite this test 

        private const int WorkItemReferenceId2 = 2067;
        private const int WorkItemReferenceId = 2077;
        private const int DocumentId = 5778;
        private const int ProcessId = 105;
        //private const int WorkItemId = 2307;
        private const int WorkItemId = 2087;
        private readonly DocumentControllerApi _documentControllerApi;
        private readonly SessionApi _sessionApi;

        public DocumentControllerApiTest()
        {
            _sessionApi = new SessionApi();
            _documentControllerApi = new DocumentControllerApi(_sessionApi.SessionStorage);
        }

        [OneTimeSetUp]
        public async Task Init()
        {
            await _sessionApi.SignIn();
        }

        [TestCase(true)]
        [TestCase(false)] //Bug with populateContent always True
        public async Task ListDocumentFields_ShouldReturnList(bool populateContent)
        {
            var response = await _documentControllerApi.ListDocumentFields(WorkItemReferenceId2, populateContent);
            var items = JsonConvert.DeserializeObject<Response<List<DocumentListItemDTO>>>(response.Content);
            var document = items.ResponseModel.FirstOrDefault(i => i.DocumentId == DocumentId);

            Assert.Multiple(() =>
            {
                Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK), "Expected status code 200 OK");
                Assert.That(document, Is.Not.Null, $"Document with ID {DocumentId} not found in response");
                Assert.That(document.DocumentId, Is.EqualTo(DocumentId), "Returned document ID does not match expected");

                Assert.That(document.PopulatingContent, Is.EqualTo(populateContent),
                    $"Expected populatingContent to be {populateContent}");
            });
        }

        [Test]
        public async Task GetDocumentContent_ShouldReturnDocument()
        {
            var response = await _documentControllerApi.GetDocument(DocumentId);

            response.StatusCode.Should().Be(HttpStatusCode.OK);

            var envelope = JsonConvert.DeserializeObject<Response<DocumentDTO>>(response.Content);
            envelope.Should().NotBeNull();
            envelope!.ResponseModel.Should().NotBeNull();

            var document = envelope.ResponseModel!;            

            Assert.Multiple(() =>
            {
                Assert.That(document.Id, Is.EqualTo(DocumentId));
                Assert.That(document.DocumentName, Is.Not.Null.And.Not.Empty);
            });
        }
                
        [Test, Ignore ("TODO")]
        public async Task UpdateDocumentField_ShouldReturnSuccess()
        {
            var request = new UpdateDocumentFieldListRequest
            {
                DocumentId = DocumentId,
                DocumentTemplateName = "EMARK_DOC_TEMPLATE",
                FieldsToUpdate = new List<UpdateDocumentFieldRequest>
                {
                  new() { FieldName = "", FieldValue = "New Value" }
                }
            };

            var response = await _documentControllerApi.UpdateDocumentField(request);
            Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
        }

        [Test]
        //Bug, should be not found
        public async Task DeleteNotExistedDocument_ShouldReturnSuccess()
        {
            var response = await _documentControllerApi.DeleteDocument(111111, permanently: false);
            Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
        }

        [Test]//, Ignore("TODO")]
        public async Task AddDocument_ShouldReturnSuccess()
        {
            // Arrange
            var filePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestFiles", "testFile.pdf");
            Assert.That(File.Exists(filePath), Is.True, $"Test file not found: {filePath}");
            byte[] fileBytes = File.ReadAllBytes(filePath);

            var requestBody = new AddDocumentRequest
            {
                ProcessId = ProcessId,
                WorkItemId = WorkItemReferenceId,
                DocumentTemplateId = 1,
                DocumentTemplateName = "DefaultTemplate",
                DocumentName = "testFile.pdf",
                DocumentFile = fileBytes,
                DisplayOrder = null,
                Fields = new List<UpdateDocumentFieldRequest>() 
            };

            // Act
            var response = await _documentControllerApi.AddDocument(requestBody);

            TestContext.WriteLine($"Status: {response.StatusCode}");
            TestContext.WriteLine(response.Content);

            // Assert
            Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK),
                $"AddDocument failed. Content: {response.Content}");
        }

        [Test]
        public async Task UpdateDocumentContent_ShouldReturnSuccess()
        {
            var request = new UpdateDocumentContentRequest
            {
                ProcessId = ProcessId,
                DocumentId = DocumentId,
                DocumentFile = new byte[] { 1, 2, 3, 4 },
                WorkItemReferenceId = WorkItemReferenceId2
            };

            var response = await _documentControllerApi.UpdateDocumentContent(request);

            response.StatusCode.Should().Be(HttpStatusCode.OK);

            var result = JsonConvert.DeserializeObject(response.Content);
            result.Should().NotBeNull();
        }

        [Test]
        public async Task DeleteDocument_ShouldReturnSuccess_WhenExists()
        {
            var filePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestFiles", "testFile.pdf");
            var fileBytes = File.ReadAllBytes(filePath);

            var requestBody = new AddDocumentRequest
            {
                ProcessId = ProcessId,
                WorkItemId = WorkItemReferenceId,
                DocumentTemplateId = 1,
                DocumentTemplateName = "DefaultTemplate",
                DocumentName = "testFile.pdf",
                DocumentFile = fileBytes,
                Fields = new List<UpdateDocumentFieldRequest>()
            };

            var addResponse = await _documentControllerApi.AddDocument(requestBody);            

            var deleteResponse = await _documentControllerApi.DeleteDocument(addResponse.Data.ResponseModel.DocumentId, permanently: true);
            deleteResponse.StatusCode.Should().Be(HttpStatusCode.OK);
        }
        
        // Be aware of pdf
        [Test]
        public async Task UpdateDocumentName_ShouldReturnBadRequest_WhenInvalidId()
        {
            var name = StringRandom.Fast(10) + ".pdf";
            var request = new RenameDocumentRequest
            {
                ProcessId = ProcessId,
                DocumentId = DocumentId,
                NewName = name
            };

            var response = await _documentControllerApi.UpdateDocumentName(request);

            response.StatusCode.Should().Be(HttpStatusCode.OK);
            response.Data.ResponseModel.DocumentName.Should().Be(name);
        }     
    }
}