using System.Net;
using System.Net.Http.Json;
using CashLineERP.Contracts.Finance;

namespace CashLineERP.Api.Tests;

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

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

    [Fact]
    public async Task Collections_Workbench_Endpoints_Return_Overdue_Items_And_Follow_Up_History()
    {
        await _client.AuthenticateAsFinanceMakerAsync();

        var invoiceResponse = await _client.PostAsJsonAsync("/api/v1/finance/ar-invoices", new CreateAccountsReceivableInvoiceRequest(
            CustomerId: 2,
            SalesOrderId: 1,
            DispatchOrderId: 1,
            InvoiceType: "TAX",
            InvoiceDate: new DateOnly(2026, 4, 1),
            TaxDate: new DateOnly(2026, 4, 1),
            DueDate: new DateOnly(2026, 4, 10),
            CurrencyCode: "EGP",
            Lines:
            [
                new CreateAccountsReceivableInvoiceLineRequest(1, 1001, 2m, "EA", 100m, "VAT14")
            ]));
        Assert.True(invoiceResponse.IsSuccessStatusCode, await invoiceResponse.Content.ReadAsStringAsync());
        var invoice = await invoiceResponse.Content.ReadFromJsonAsync<AccountsReceivableInvoiceResponse>();
        Assert.NotNull(invoice);

        var submitResponse = await _client.PostAsync($"/api/v1/finance/ar-invoices/{invoice!.AccountsReceivableInvoiceId}/submit", null);
        Assert.True(submitResponse.IsSuccessStatusCode, await submitResponse.Content.ReadAsStringAsync());

        await _client.AuthenticateAsFinanceCheckerAsync();
        var approveResponse = await _client.PostAsync($"/api/v1/finance/ar-invoices/{invoice.AccountsReceivableInvoiceId}/approve", null);
        Assert.True(approveResponse.IsSuccessStatusCode, await approveResponse.Content.ReadAsStringAsync());

        var postResponse = await _client.PostAsync($"/api/v1/finance/ar-invoices/{invoice.AccountsReceivableInvoiceId}/post", null);
        Assert.True(postResponse.IsSuccessStatusCode, await postResponse.Content.ReadAsStringAsync());

        var summaryResponse = await _client.GetAsync("/api/v1/finance/collections/workbench?asOfDate=2026-04-30");
        Assert.Equal(HttpStatusCode.OK, summaryResponse.StatusCode);
        var summary = await summaryResponse.Content.ReadFromJsonAsync<CollectionsWorkbenchSummaryResponse>();
        Assert.NotNull(summary);
        Assert.Equal(1, summary!.OverdueInvoiceCount);

        var followUpResponse = await _client.PostAsJsonAsync($"/api/v1/finance/collections/invoices/{invoice.AccountsReceivableInvoiceId}/follow-up", new RecordCollectionsFollowUpRequest(
            ActionDate: new DateOnly(2026, 4, 22),
            ActionTypeCode: "EMAIL",
            OutcomeCode: "PROMISED",
            PromiseToPayDate: new DateOnly(2026, 4, 28),
            NextFollowUpDate: new DateOnly(2026, 4, 29),
            Notes: "Finance emailed the customer for overdue settlement."));
        Assert.Equal(HttpStatusCode.OK, followUpResponse.StatusCode);
        var followUp = await followUpResponse.Content.ReadFromJsonAsync<CollectionsFollowUpActionResponse>();
        Assert.NotNull(followUp);
        Assert.Equal("EMAIL", followUp!.ActionTypeCode);

        var queueResponse = await _client.GetAsync("/api/v1/finance/collections/queue?asOfDate=2026-04-30&actionRequiredOnly=true");
        Assert.Equal(HttpStatusCode.OK, queueResponse.StatusCode);
        var queue = await queueResponse.Content.ReadFromJsonAsync<List<CollectionsQueueItemResponse>>();
        Assert.NotNull(queue);
        var queueItem = Assert.Single(queue!);
        Assert.Equal(invoice.AccountsReceivableInvoiceId, queueItem.AccountsReceivableInvoiceId);
        Assert.Equal("EMAIL", queueItem.LastFollowUpActionTypeCode);
        Assert.Equal("PROMISED", queueItem.LastFollowUpOutcomeCode);
        Assert.True(queueItem.ActionRequired);

        var historyResponse = await _client.GetAsync($"/api/v1/finance/collections/invoices/{invoice.AccountsReceivableInvoiceId}/follow-ups");
        Assert.Equal(HttpStatusCode.OK, historyResponse.StatusCode);
        var history = await historyResponse.Content.ReadFromJsonAsync<List<CollectionsFollowUpActionResponse>>();
        Assert.NotNull(history);
        Assert.Single(history!);
        Assert.Equal(followUp.CollectionsFollowUpActionId, history[0].CollectionsFollowUpActionId);

        var customerSummaryResponse = await _client.GetAsync("/api/v1/finance/collections/customers/2/summary?asOfDate=2026-04-30&currencyCode=EGP");
        Assert.Equal(HttpStatusCode.OK, customerSummaryResponse.StatusCode);
        var customerSummary = await customerSummaryResponse.Content.ReadFromJsonAsync<CollectionsCustomerSummaryResponse>();
        Assert.NotNull(customerSummary);
        Assert.Equal(2, customerSummary!.CustomerId);
        Assert.Equal("EGP", customerSummary.CurrencyCode);
        Assert.Equal(1, customerSummary.OverdueInvoiceCount);
        Assert.Equal(queueItem.OutstandingAmount, customerSummary.TotalOutstandingAmount);
        Assert.Equal(1, customerSummary.ActionRequiredCount);
        Assert.Equal(1, customerSummary.PromiseToPayCount);
        Assert.Equal(1, customerSummary.BrokenPromiseCount);
        Assert.Equal(1, customerSummary.NextFollowUpDueCount);
        Assert.Single(customerSummary.Queue);
        Assert.Single(customerSummary.RecentActions);
    }
}
