using System.Net;
using System.Net.Http.Json;
using System.Linq;
using CashLineERP.Contracts.IslamicFinance;

namespace CashLineERP.Api.Tests;

[Collection("Islamic Finance HTTP QA")]
public sealed class IslamicFinanceReceivablesFinanceQaTests : IClassFixture<ApiTestFactory>
{
    private readonly HttpClient _client;

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

    [Fact]
    public async Task Islamic_Finance_Receivables_HTTP_Supports_Eligibility_Create_Lifecycle_And_Audit_Reads()
    {
        var setup = await IslamicFinanceReceivablesFinanceSeedHelper.SeedHttpScenarioAsync(_client, "IFRF-HTTP");

        await _client.AuthenticateAsInternalAsync();
        var eligibilityBeforeResponse = await _client.GetAsync("/api/v1/sales/customers/2/receivables-finance-eligibility?currencyCode=EGP&asOfDate=2026-04-20");
        Assert.Equal(HttpStatusCode.OK, eligibilityBeforeResponse.StatusCode);
        var eligibilityBefore = await eligibilityBeforeResponse.Content.ReadFromJsonAsync<IslamicFinanceReceivablesEligibilityInvoiceResponse[]>();
        Assert.NotNull(eligibilityBefore);
        var invoiceBefore = Assert.Single(eligibilityBefore!, entry => entry.AccountsReceivableInvoiceId == setup.InvoiceId);
        Assert.False(invoiceBefore.IsAlreadyLinked);

        var createResponse = await _client.PostAsJsonAsync("/api/v1/islamic-finance/receivables-cases", new CreateIslamicFinanceReceivablesCaseRequest
        {
            CaseNumber = $"IFRF-{Guid.NewGuid():N}"[..12].ToUpperInvariant(),
            FinancingRequestId = setup.RequestId,
            Lines =
            [
                new CreateIslamicFinanceReceivablesCaseLineRequest
                {
                    AccountsReceivableInvoiceId = setup.InvoiceId,
                    FinancedAmount = 80m
                }
            ]
        });
        Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);
        var created = await createResponse.Content.ReadFromJsonAsync<IslamicFinanceReceivablesCaseResponse>();
        Assert.NotNull(created);
        Assert.Equal("DRAFT", created!.StatusCode);

        var listResponse = await _client.GetAsync($"/api/v1/islamic-finance/receivables-cases?customerPartyId=2&partnerLenderId={setup.PartnerId}");
        Assert.Equal(HttpStatusCode.OK, listResponse.StatusCode);
        var listed = await listResponse.Content.ReadFromJsonAsync<IslamicFinanceReceivablesCaseResponse[]>();
        Assert.NotNull(listed);
        Assert.Contains(listed!, entry => entry.Id == created.Id);

        var detailResponse = await _client.GetAsync($"/api/v1/islamic-finance/receivables-cases/{created.Id}");
        Assert.Equal(HttpStatusCode.OK, detailResponse.StatusCode);

        Assert.Equal(HttpStatusCode.OK, (await _client.PostAsync($"/api/v1/islamic-finance/receivables-cases/{created.Id}/submit", null)).StatusCode);

        await _client.AuthenticateAsFinanceCheckerAsync();
        Assert.Equal(HttpStatusCode.OK, (await _client.PostAsync($"/api/v1/islamic-finance/receivables-cases/{created.Id}/approve", null)).StatusCode);
        var activateResponse = await _client.PostAsync($"/api/v1/islamic-finance/receivables-cases/{created.Id}/activate", null);
        Assert.Equal(HttpStatusCode.OK, activateResponse.StatusCode);
        var activated = await activateResponse.Content.ReadFromJsonAsync<IslamicFinanceReceivablesCaseResponse>();
        Assert.NotNull(activated);
        Assert.Equal("ACTIVE", activated!.StatusCode);

        await _client.AuthenticateAsInternalAsync();
        var historyResponse = await _client.GetAsync($"/api/v1/islamic-finance/receivables-cases/{created.Id}/history");
        Assert.Equal(HttpStatusCode.OK, historyResponse.StatusCode);
        var history = await historyResponse.Content.ReadFromJsonAsync<IslamicFinanceLifecycleHistoryEntryResponse[]>();
        Assert.NotNull(history);
        Assert.Contains(history!, entry => entry.EventCode == "RECEIVABLES_CASE_CREATED");
        Assert.Contains(history!, entry => entry.EventCode == "RECEIVABLES_CASE_ACTIVATED");

        var auditResponse = await _client.GetAsync($"/api/v1/islamic-finance/receivables-cases/{created.Id}/audit");
        Assert.Equal(HttpStatusCode.OK, auditResponse.StatusCode);
        var audit = await auditResponse.Content.ReadFromJsonAsync<IslamicFinanceReceivablesCaseAuditResponse>();
        Assert.NotNull(audit);
        Assert.Equal(created.Id, audit!.ReceivablesCase.Id);
        Assert.Contains(audit.Events, entry => entry.EventCode == "RECEIVABLE_INVOICE_ACTIVATED");

        var eligibilityAfterResponse = await _client.GetAsync("/api/v1/sales/customers/2/receivables-finance-eligibility?currencyCode=EGP&asOfDate=2026-04-20");
        Assert.Equal(HttpStatusCode.OK, eligibilityAfterResponse.StatusCode);
        var eligibilityAfter = await eligibilityAfterResponse.Content.ReadFromJsonAsync<IslamicFinanceReceivablesEligibilityInvoiceResponse[]>();
        Assert.NotNull(eligibilityAfter);
        var invoiceAfter = Assert.Single(eligibilityAfter!, entry => entry.AccountsReceivableInvoiceId == setup.InvoiceId);
        Assert.True(invoiceAfter.IsAlreadyLinked);
    }

    [Fact]
    public async Task Islamic_Finance_Receivables_HTTP_Blocks_Duplicate_Invoice_Relinkage()
    {
        var setup = await IslamicFinanceReceivablesFinanceSeedHelper.SeedHttpScenarioAsync(_client, "IFRF-DUP");

        await _client.AuthenticateAsInternalAsync();
        var firstCreateResponse = await _client.PostAsJsonAsync("/api/v1/islamic-finance/receivables-cases", new CreateIslamicFinanceReceivablesCaseRequest
        {
            CaseNumber = $"IFRF-{Guid.NewGuid():N}"[..12].ToUpperInvariant(),
            FinancingRequestId = setup.RequestId,
            Lines =
            [
                new CreateIslamicFinanceReceivablesCaseLineRequest
                {
                    AccountsReceivableInvoiceId = setup.InvoiceId,
                    FinancedAmount = 75m
                }
            ]
        });
        Assert.Equal(HttpStatusCode.OK, firstCreateResponse.StatusCode);

        var duplicateResponse = await _client.PostAsJsonAsync("/api/v1/islamic-finance/receivables-cases", new CreateIslamicFinanceReceivablesCaseRequest
        {
            CaseNumber = $"IFRF-{Guid.NewGuid():N}"[..12].ToUpperInvariant(),
            FinancingRequestId = setup.RequestId,
            Lines =
            [
                new CreateIslamicFinanceReceivablesCaseLineRequest
                {
                    AccountsReceivableInvoiceId = setup.InvoiceId,
                    FinancedAmount = 70m
                }
            ]
        });

        Assert.Equal(HttpStatusCode.BadRequest, duplicateResponse.StatusCode);
    }
}
