using CashLineERP.Application.IslamicFinance.Murabaha;
using CashLineERP.Contracts.IslamicFinance;
using CashLineERP.Domain.IslamicFinance.Murabaha;
using CashLineERP.Infrastructure.Persistence;
using CashLineERP.Infrastructure.Persistence.Repositories.IslamicFinance;

namespace CashLineERP.Api.Tests;

public sealed class IslamicFinanceMurabahaScheduleServiceQaTests
{
    [Fact]
    public void Murabaha_Schedule_Service_Generates_And_Returns_Case_Summary_And_Ordered_Lines()
    {
        using var dbContext = QaDbContextFactory.CreateContext();
        var murabahaCaseId = SeedApprovedMurabahaCase(dbContext);

        var service = new MurabahaCaseService(new MurabahaCaseRepository(dbContext));
        service.GenerateSchedule(murabahaCaseId, 7, new GenerateIslamicFinanceMurabahaScheduleRequest
        {
            InstallmentCount = 2,
            FirstDueDate = new DateOnly(2026, 5, 1),
            InstallmentIntervalMonths = 1
        });

        var schedule = service.GetSchedule(murabahaCaseId);

        Assert.NotNull(schedule);
        Assert.Equal(murabahaCaseId, schedule!.MurabahaCaseId);
        Assert.Equal("MUR-CASE-001", schedule.CaseNumber);
        Assert.Equal(2, schedule.InstallmentCount);
        Assert.Collection(
            schedule.Lines,
            first => Assert.Equal(1, first.InstallmentNumber),
            second => Assert.Equal(2, second.InstallmentNumber));
    }

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

        var service = new MurabahaCaseService(new MurabahaCaseRepository(dbContext));
        service.GenerateSchedule(murabahaCaseId, 7, new GenerateIslamicFinanceMurabahaScheduleRequest
        {
            InstallmentCount = 2,
            FirstDueDate = new DateOnly(2026, 5, 1),
            InstallmentIntervalMonths = 1
        });

        var installment = service.GetScheduleInstallment(murabahaCaseId, 2);

        Assert.NotNull(installment);
        Assert.Equal(2, installment!.InstallmentNumber);
        Assert.Equal(60000m, installment.InstallmentAmount);
        Assert.Equal(0m, installment.OutstandingBalanceAmount);
    }

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

        var service = new MurabahaCaseService(new MurabahaCaseRepository(dbContext));
        service.GenerateSchedule(murabahaCaseId, 7, new GenerateIslamicFinanceMurabahaScheduleRequest
        {
            InstallmentCount = 2,
            FirstDueDate = new DateOnly(2026, 5, 1),
            InstallmentIntervalMonths = 1
        });

        var regenerated = service.GenerateSchedule(murabahaCaseId, 8, new GenerateIslamicFinanceMurabahaScheduleRequest
        {
            InstallmentCount = 3,
            FirstDueDate = new DateOnly(2026, 6, 1),
            InstallmentIntervalMonths = 1
        });

        Assert.Equal(3, regenerated.InstallmentCount);
        Assert.Equal(5, dbContext.IslamicFinanceProfitSchedules.Count());
        Assert.Equal(3, dbContext.IslamicFinanceProfitSchedules.Count(entry => entry.StatusCode == "ACTIVE"));
        Assert.Equal(2, dbContext.IslamicFinanceProfitSchedules.Count(entry => entry.StatusCode == "SUSPENDED"));
    }

    private static long SeedApprovedMurabahaCase(CashLineErpDbContext dbContext)
    {
        var murabahaCase = new IslamicFinanceMurabahaCase(
            "MUR-CASE-001",
            101,
            1,
            1,
            supplierPartyId: 2,
            productProfileId: 1,
            contractTemplateId: null,
            transactionCurrencyCode: "EGP",
            purchaseCostAmount: 100000m,
            profitAmount: 20000m);

        murabahaCase.Submit(3);
        murabahaCase.Approve(4);
        murabahaCase.Activate(4);
        dbContext.IslamicFinanceMurabahaCases.Add(murabahaCase);
        dbContext.SaveChanges();

        return murabahaCase.Id;
    }
}
