using System.Net;
using System.Net.Http.Json;
using CashLineERP.Contracts.Documents;
using CashLineERP.Contracts.Parties;
using CashLineERP.SharedKernel.Documents;

namespace CashLineERP.Api.Tests;

public sealed class DocumentStorageLifecycleQaTests : IClassFixture<ApiTestFactory>
{
    private readonly HttpClient _client;

    public DocumentStorageLifecycleQaTests(ApiTestFactory factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task Document_Lifecycle_Endpoints_Work_End_To_End()
    {
        await _client.AuthenticateAsInternalAsync();

        var createResponse = await _client.PostAsJsonAsync("/api/v1/documents", new CreateDocumentAttachmentRequest(
            ModuleCode: "FINANCE",
            EntityName: "CUSTOMER_STATEMENT",
            EntityId: 1,
            DocumentType: "STATEMENT_PDF",
            AttachmentCategoryCode: DocumentAttachmentCategoryCode.Statement,
            FileName: "statement-apr-2026.pdf",
            StorageReference: "statements/customer/1/statement-apr-2026.pdf",
            StorageProviderCode: DocumentStorageProviderCode.ManagedStorage,
            ContentType: "application/pdf",
            FileSizeBytes: 14400,
            ChecksumText: "sha256:statement-apr-2026",
            RetentionUntilUtc: new DateTime(2028, 4, 5, 0, 0, 0, DateTimeKind.Utc)));
        Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);

        var createdDocument = await createResponse.Content.ReadFromJsonAsync<DocumentAttachmentResponse>();
        Assert.NotNull(createdDocument);
        Assert.Equal("ACTIVE", createdDocument!.LifecycleStatusCode);

        var listResponse = await _client.GetAsync("/api/v1/documents?moduleCode=FINANCE&entityName=CUSTOMER_STATEMENT&entityId=1&lifecycleStatusCode=ACTIVE");
        Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);

        var listedDocuments = await listResponse.Content.ReadFromJsonAsync<DocumentAttachmentResponse[]>();
        Assert.NotNull(listedDocuments);
        Assert.Contains(listedDocuments!, document => document.DocumentLinkId == createdDocument.DocumentLinkId);

        var supersedeResponse = await _client.PostAsJsonAsync($"/api/v1/documents/{createdDocument.DocumentLinkId}/supersede", new SupersedeDocumentAttachmentRequest(
            FileName: "statement-apr-2026-v2.pdf",
            StorageReference: "statements/customer/1/statement-apr-2026-v2.pdf",
            StorageProviderCode: DocumentStorageProviderCode.ManagedStorage,
            ContentType: "application/pdf",
            FileSizeBytes: 15500,
            ChecksumText: "sha256:statement-apr-2026-v2",
            RetentionUntilUtc: new DateTime(2028, 4, 5, 0, 0, 0, DateTimeKind.Utc),
            ReasonText: "Regenerated with corrected opening balance"));
        Assert.Equal(HttpStatusCode.OK, supersedeResponse.StatusCode);

        var supersededDocument = await supersedeResponse.Content.ReadFromJsonAsync<DocumentAttachmentResponse>();
        Assert.NotNull(supersededDocument);
        Assert.Equal(2, supersededDocument!.VersionNumber);

        var originalDetailResponse = await _client.GetAsync($"/api/v1/documents/{createdDocument.DocumentLinkId}");
        Assert.Equal(HttpStatusCode.OK, originalDetailResponse.StatusCode);
        var originalDocument = await originalDetailResponse.Content.ReadFromJsonAsync<DocumentAttachmentResponse>();
        Assert.NotNull(originalDocument);
        Assert.Equal("SUPERSEDED", originalDocument!.LifecycleStatusCode);

        var archiveResponse = await _client.PostAsJsonAsync($"/api/v1/documents/{supersededDocument.DocumentLinkId}/archive", new ArchiveDocumentAttachmentRequest(
            ReasonText: "Archived after superseded statement was externally delivered"));
        Assert.Equal(HttpStatusCode.OK, archiveResponse.StatusCode);

        var archivedDocument = await archiveResponse.Content.ReadFromJsonAsync<DocumentAttachmentResponse>();
        Assert.NotNull(archivedDocument);
        Assert.Equal("ARCHIVED", archivedDocument!.LifecycleStatusCode);
    }

    [Fact]
    public async Task Party_Compliance_Endpoints_Only_Show_Active_Documents()
    {
        await _client.AuthenticateAsInternalAsync();

        var createResponse = await _client.PostAsJsonAsync("/api/v1/parties/1/compliance-documents", new RecordBusinessPartyComplianceDocumentRequest(
            DocumentType: "vat_certificate",
            FileName: "vat-certificate-v1.pdf",
            StorageReference: "party/1/vat-certificate-v1.pdf",
            ContentType: "application/pdf",
            FileSizeBytes: 2048));
        Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);

        var createdDocument = await createResponse.Content.ReadFromJsonAsync<BusinessPartyComplianceDocumentResponse>();
        Assert.NotNull(createdDocument);

        var supersedeResponse = await _client.PostAsJsonAsync($"/api/v1/documents/{createdDocument!.DocumentLinkId}/supersede", new SupersedeDocumentAttachmentRequest(
            FileName: "vat-certificate-v2.pdf",
            StorageReference: "party/1/vat-certificate-v2.pdf",
            StorageProviderCode: DocumentStorageProviderCode.ManagedStorage,
            ContentType: "application/pdf",
            FileSizeBytes: 3072,
            ChecksumText: "sha256:vat-cert-v2",
            RetentionUntilUtc: null,
            ReasonText: "Renewed VAT certificate"));
        Assert.Equal(HttpStatusCode.OK, supersedeResponse.StatusCode);

        var listResponse = await _client.GetAsync("/api/v1/parties/1/compliance-documents");
        Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);

        var documents = await listResponse.Content.ReadFromJsonAsync<BusinessPartyComplianceDocumentResponse[]>();
        Assert.NotNull(documents);
        Assert.DoesNotContain(documents!, document => document.DocumentLinkId == createdDocument.DocumentLinkId);
        Assert.Contains(documents!, document => document.FileName == "vat-certificate-v2.pdf");
    }
}
