using CashLineERP.Application.Finance;
using CashLineERP.Contracts.Finance;
using CashLineERP.Infrastructure.Persistence.Repositories;

namespace CashLineERP.Api.Tests;

public sealed class CollectionsWorkbenchServiceQaTests
{
    [Fact]
    public void Collections_Workbench_Returns_Overdue_Queue_And_Follow_Up_State()
    {
        using var dbContext = QaDbContextFactory.CreateContext();

        var invoiceService = new AccountsReceivableInvoiceService(new AccountsReceivableInvoiceRepository(dbContext));
        var receiptService = new AccountsReceivableReceiptService(new AccountsReceivableReceiptRepository(dbContext));
        var collectionsService = new CollectionsWorkbenchService(new CollectionsWorkbenchRepository(dbContext));

        var invoice = AccountsReceivableWorkflowTestHelper.SubmitApproveAndPostInvoice(
            invoiceService,
            invoiceService.CreateInvoice(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")
                ])).AccountsReceivableInvoiceId);

        var receipt = AccountsReceivableWorkflowTestHelper.SubmitApproveAndPostReceipt(
            receiptService,
            receiptService.CreateReceipt(new CreateAccountsReceivableReceiptRequest(
                CustomerId: 2,
                ReceiptDate: new DateOnly(2026, 4, 12),
                ReceiptMethod: "BANK_TRANSFER",
                CurrencyCode: "EGP",
                AmountAmount: 80m,
                ReferenceNumber: "COLL-RCPT-0001",
                Notes: "Partial settlement",
                Allocations:
                [
                    new CreateAccountsReceivableReceiptAllocationRequest(invoice.AccountsReceivableInvoiceId, 80m, new DateOnly(2026, 4, 12))
                ])).AccountsReceivableReceiptId);

        Assert.Equal("POSTED", receipt.StatusCode);

        var summary = collectionsService.GetSummary(new DateOnly(2026, 4, 30));
        Assert.Equal(1, summary.OverdueInvoiceCount);
        Assert.Equal(1, summary.OverdueCustomerCount);
        Assert.Equal(invoice.TotalAmount - 80m, summary.TotalOutstandingAmount);
        Assert.Equal(1, summary.ActionRequiredCount);

        var followUp = collectionsService.RecordFollowUp(invoice.AccountsReceivableInvoiceId, 2, new RecordCollectionsFollowUpRequest(
            ActionDate: new DateOnly(2026, 4, 20),
            ActionTypeCode: "call",
            OutcomeCode: "promised",
            PromiseToPayDate: new DateOnly(2026, 4, 24),
            NextFollowUpDate: new DateOnly(2026, 4, 25),
            Notes: "Customer promised to settle remaining balance."));

        Assert.Equal("CALL", followUp.ActionTypeCode);
        Assert.Equal("PROMISED", followUp.OutcomeCode);

        var queue = collectionsService.GetQueue(new DateOnly(2026, 4, 30), actionRequiredOnly: true);
        var queueItem = Assert.Single(queue);
        Assert.Equal(invoice.AccountsReceivableInvoiceId, queueItem.AccountsReceivableInvoiceId);
        Assert.Equal(invoice.TotalAmount - 80m, queueItem.OutstandingAmount);
        Assert.Equal(20, queueItem.OverdueDays);
        Assert.Equal("1_30", queueItem.AgingBucketCode);
        Assert.Equal(new DateOnly(2026, 4, 20), queueItem.LastFollowUpActionDate);
        Assert.Equal("CALL", queueItem.LastFollowUpActionTypeCode);
        Assert.Equal("PROMISED", queueItem.LastFollowUpOutcomeCode);
        Assert.Equal(new DateOnly(2026, 4, 24), queueItem.PromiseToPayDate);
        Assert.Equal(new DateOnly(2026, 4, 25), queueItem.NextFollowUpDate);
        Assert.True(queueItem.ActionRequired);

        var history = collectionsService.GetFollowUpActions(invoice.AccountsReceivableInvoiceId);
        var action = Assert.Single(history);
        Assert.Equal(followUp.CollectionsFollowUpActionId, action.CollectionsFollowUpActionId);

        var refreshedSummary = collectionsService.GetSummary(new DateOnly(2026, 4, 30));
        Assert.Equal(1, refreshedSummary.PromiseToPayCount);
        Assert.Equal(1, refreshedSummary.BrokenPromiseCount);

        var customerSummary = collectionsService.GetCustomerSummary(2, new DateOnly(2026, 4, 30), "EGP");
        Assert.Equal(2, customerSummary.CustomerId);
        Assert.Equal("EGP", customerSummary.CurrencyCode);
        Assert.Equal(1, customerSummary.OverdueInvoiceCount);
        Assert.Equal(invoice.TotalAmount - 80m, 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);
    }
}
