using DocumentOperator.API.Controllers; // For ExtractSwissQrCodeBase64Request DTO
using DocumentOperator.Application.Common.DTOs;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using Xunit;

namespace DocumentOperator.Tests.Integration.API;

public sealed class ExtractSwissQrCodeEndpointTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly HttpClient _client;
    private readonly JsonSerializerOptions _jsonOptions;

    public ExtractSwissQrCodeEndpointTests(WebApplicationFactory<Program> factory)
    {
        _client = factory.CreateClient();
        _jsonOptions = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        };
    }

    [Fact]
    public async Task POST_ExtractSwissQrCode_ValidRequest_Returns200()
    {
        // Arrange
        var validPdfBase64 = GetEmbeddedResourceAsBase64("DocumentOperator.Tests.TestData.Pdfs.valid.pdf");

        var request = new ExtractSwissQrCodeBase64Request
        {
            Base64Pdf = validPdfBase64
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/pdf/qr-code/extract-swiss", request);

        // Assert
        // Note: The test PDF (valid.pdf) may not actually contain a Swiss QR Code
        // so this test might return 404. We're testing the endpoint wiring here.
        // A real test would need a PDF with a Swiss QR Code on the last page.
        response.StatusCode.Should().BeOneOf(HttpStatusCode.OK, HttpStatusCode.NotFound);

        if (response.StatusCode == HttpStatusCode.OK)
        {
            var result = await response.Content.ReadFromJsonAsync<SwissQrCodeExtractionResult>(_jsonOptions);
            result.Should().NotBeNull();
            result.Bill.Should().NotBeNull();
            result.RawLines.Should().NotBeEmpty();
        }
    }

    [Fact]
    public async Task POST_ExtractSwissQrCode_InvalidBase64_Returns400()
    {
        // Arrange
        var request = new ExtractSwissQrCodeBase64Request
        {
            Base64Pdf = "INVALID_BASE64!!!"
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/pdf/qr-code/extract-swiss", request);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
        
        var problemDetails = await response.Content.ReadAsStringAsync();
        // FormatException message contains "Base-64" (with hyphen)
        problemDetails.Should().MatchRegex("(?i)base.?64", "should contain Base64 validation error");
    }

    [Fact]
    public async Task POST_ExtractSwissQrCode_NullReferences_AcceptedByValidation()
    {
        // Arrange: References are OPTIONAL - null should not cause validation error (400)
        // Using pdfWithSwissQRCode.pdf which actually has a QR code, so we get 200
        var validPdfBase64 = GetEmbeddedResourceAsBase64("DocumentOperator.Tests.TestData.Pdfs.pdfWithSwissQRCode.pdf");

        var request = new
        {
            References = (List<string>?)null, // Optional field - should not cause 400
            Base64Pdf = validPdfBase64
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/pdf/qr-code/extract-swiss", request);

        // Assert: Should NOT be 400 (validation error), should be 200 or 404
        response.StatusCode.Should().NotBe(HttpStatusCode.BadRequest, 
            "null References should be accepted (optional field)");
        
        // If extraction succeeds, verify empty references array
        if (response.StatusCode == HttpStatusCode.OK)
        {
            var result = await response.Content.ReadFromJsonAsync<SwissQrCodeExtractionResult>();
            result.Should().NotBeNull();
        }
    }

    [Fact]
    public async Task POST_ExtractSwissQrCode_EmptyPdf_Returns400()
    {
        // Arrange
        var request = new
        {
            References = new List<string> { "REF-001" },
            Base64Pdf = (string?)null
        };

        // Act
        var response = await _client.PostAsJsonAsync("/api/pdf/qr-code/extract-swiss", request);

        // Assert
        response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
    }

    /// <summary>
    /// Helper method to load embedded resource as Base64 string
    /// </summary>
    private static string GetEmbeddedResourceAsBase64(string resourceName)
    {
        var assembly = typeof(ExtractSwissQrCodeEndpointTests).Assembly;
        using var stream = assembly.GetManifestResourceStream(resourceName);

        if (stream == null)
        {
            throw new FileNotFoundException($"Embedded resource not found: {resourceName}");
        }

        using var memoryStream = new MemoryStream();
        stream.CopyTo(memoryStream);
        return Convert.ToBase64String(memoryStream.ToArray());
    }
}
