using System.Linq;
using CashLineERP.Application.IslamicFinance.ReceivablesFinance;
using CashLineERP.Contracts.IslamicFinance;
using CashLineERP.Infrastructure.Persistence.Repositories.IslamicFinance;

namespace CashLineERP.Api.Tests;

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

        var service = new ReceivablesFinanceService(new ReceivablesFinanceRepository(dbContext));
        var setup = IslamicFinanceReceivablesFinanceSeedHelper.SeedServiceScenario(dbContext, "IFRF-SVC");

        var eligibleBefore = service.GetEligibleInvoices(2, "EGP", new DateOnly(2026, 4, 20));
        var eligibleInvoiceBefore = Assert.Single(eligibleBefore, entry => entry.AccountsReceivableInvoiceId == setup.InvoiceId);
        Assert.False(eligibleInvoiceBefore.IsAlreadyLinked);
        Assert.True(eligibleInvoiceBefore.OutstandingAmount > 0m);

        var created = service.CreateCase(new CreateIslamicFinanceReceivablesCaseRequest
        {
            CaseNumber = "IFRF-SVC-001",
            FinancingRequestId = setup.RequestId,
            Lines =
            [
                new CreateIslamicFinanceReceivablesCaseLineRequest
                {
                    AccountsReceivableInvoiceId = setup.InvoiceId,
                    FinancedAmount = 80m
                }
            ]
        });

        Assert.Equal("DRAFT", created.StatusCode);
        Assert.Single(created.Lines);
        Assert.Equal(setup.InvoiceId, created.Lines.Single().AccountsReceivableInvoiceId);

        service.SubmitCase(created.Id, 20);
        service.ApproveCase(created.Id, 21);
        var activated = service.ActivateCase(created.Id, 21);

        Assert.Equal("ACTIVE", activated.StatusCode);
        Assert.Equal("ACTIVE", activated.Lines.Single().StatusCode);
        Assert.NotNull(activated.ActivatedAtUtc);

        var history = service.GetCaseHistory(created.Id);
        Assert.Contains(history, entry => entry.EventCode == "RECEIVABLES_CASE_CREATED");
        Assert.Contains(history, entry => entry.EventCode == "RECEIVABLE_INVOICE_LINKED");
        Assert.Contains(history, entry => entry.EventCode == "RECEIVABLES_CASE_ACTIVATED");
        Assert.True(history.SequenceEqual(history.OrderBy(entry => entry.OccurredAtUtc)));

        var audit = service.GetCaseAudit(created.Id);
        Assert.NotNull(audit);
        Assert.Equal(created.Id, audit!.ReceivablesCase.Id);
        Assert.Contains(audit.Events, entry => entry.EventCode == "RECEIVABLE_INVOICE_ACTIVATED");

        var eligibleAfter = service.GetEligibleInvoices(2, "EGP", new DateOnly(2026, 4, 20));
        var eligibleInvoiceAfter = Assert.Single(eligibleAfter, entry => entry.AccountsReceivableInvoiceId == setup.InvoiceId);
        Assert.True(eligibleInvoiceAfter.IsAlreadyLinked);
    }

    [Fact]
    public void Islamic_Finance_Receivables_Service_Rejects_Duplicate_Invoice_Relinkage()
    {
        using var dbContext = QaDbContextFactory.CreateContext();

        var service = new ReceivablesFinanceService(new ReceivablesFinanceRepository(dbContext));
        var setup = IslamicFinanceReceivablesFinanceSeedHelper.SeedServiceScenario(dbContext, "IFRF-DUP");

        service.CreateCase(new CreateIslamicFinanceReceivablesCaseRequest
        {
            CaseNumber = "IFRF-DUP-001",
            FinancingRequestId = setup.RequestId,
            Lines =
            [
                new CreateIslamicFinanceReceivablesCaseLineRequest
                {
                    AccountsReceivableInvoiceId = setup.InvoiceId,
                    FinancedAmount = 75m
                }
            ]
        });

        var error = Assert.Throws<InvalidOperationException>(() => service.CreateCase(new CreateIslamicFinanceReceivablesCaseRequest
        {
            CaseNumber = "IFRF-DUP-002",
            FinancingRequestId = setup.RequestId,
            Lines =
            [
                new CreateIslamicFinanceReceivablesCaseLineRequest
                {
                    AccountsReceivableInvoiceId = setup.InvoiceId,
                    FinancedAmount = 70m
                }
            ]
        }));

        Assert.Contains("already financed", error.Message, StringComparison.OrdinalIgnoreCase);
    }
}
