using CashLineERP.Application.IslamicFinance.ProductProfiles;
using CashLineERP.Application.IslamicFinance.Requests;
using CashLineERP.Application.IslamicFinance.Shariah;
using CashLineERP.Contracts.IslamicFinance;
using CashLineERP.Infrastructure.Persistence.Repositories.IslamicFinance;

namespace CashLineERP.Api.Tests;

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

        var productService = new IslamicFinanceProductService(new IslamicFinanceProductRepository(dbContext));
        var requestService = new IslamicFinanceRequestService(new IslamicFinanceRequestRepository(dbContext));
        var shariahService = new ShariahReviewService(new ShariahReviewRepository(dbContext));

        var product = productService.CreateProductProfile(new CreateIslamicFinanceProductProfileRequest
        {
            ProductType = "MURABAHA",
            ProductCode = $"MUR-SHR-{Guid.NewGuid():N}"[..12].ToUpperInvariant(),
            ProductName = "Murabaha Shariah Product",
            RequiresShariahReview = true,
            AllowsPartnerFunding = true,
            AllowsCashLineFunding = false
        });

        var request = requestService.CreateRequest(new CreateIslamicFinanceFinancingRequestRequest
        {
            RequestNumber = "REQ-SHR-001",
            CustomerPartyId = 1,
            ProductProfileId = product.Id,
            FundingSourceMode = "PARTNER",
            SourceDocumentType = "SALES_ORDER",
            SourceDocumentId = 1003,
            TransactionCurrencyCode = "EGP",
            RequestedAmount = 110000m
        });

        var created = shariahService.CreateReviewCase(new CreateIslamicFinanceShariahReviewRequest
        {
            ReviewCaseNumber = "SHR-SVC-001",
            ProductProfileId = product.Id,
            FinancingRequestId = request.Id,
            ReviewReasonCode = "SHARIAH_REVIEW"
        });

        Assert.Equal("DRAFT", created.StatusCode);

        var submitted = shariahService.SubmitReviewCase(created.Id, 3);
        Assert.Equal("SUBMITTED", submitted.StatusCode);

        var recommended = shariahService.RecommendOutcome(created.Id, new RecommendIslamicFinanceShariahOutcomeRequest
        {
            ReviewOutcomeCode = "APPROVED",
            ReviewNotes = "Compliant with approved Murabaha structure."
        }, 3);

        Assert.Equal("APPROVED", recommended.ReviewOutcomeCode);

        var approved = shariahService.ApproveOutcome(created.Id, 4);
        Assert.Equal("APPROVED", approved.StatusCode);

        var detail = shariahService.GetReviewCase(created.Id);
        Assert.NotNull(detail);
        Assert.Equal(created.Id, detail!.Id);

        var approvedReviews = shariahService.GetReviewCases(statusCode: "APPROVED", financingRequestId: request.Id, productProfileId: product.Id);
        Assert.Single(approvedReviews);
    }

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

        var productService = new IslamicFinanceProductService(new IslamicFinanceProductRepository(dbContext));
        var shariahService = new ShariahReviewService(new ShariahReviewRepository(dbContext));

        var product = productService.CreateProductProfile(new CreateIslamicFinanceProductProfileRequest
        {
            ProductType = "MURABAHA",
            ProductCode = $"MUR-SHR-{Guid.NewGuid():N}"[..12].ToUpperInvariant(),
            ProductName = "Murabaha Self Approval Product",
            RequiresShariahReview = true,
            AllowsPartnerFunding = true,
            AllowsCashLineFunding = false
        });

        var created = shariahService.CreateReviewCase(new CreateIslamicFinanceShariahReviewRequest
        {
            ReviewCaseNumber = "SHR-SVC-002",
            ProductProfileId = product.Id,
            FinancingRequestId = null,
            ReviewReasonCode = "SHARIAH_REVIEW"
        });

        shariahService.SubmitReviewCase(created.Id, 3);
        shariahService.RecommendOutcome(created.Id, new RecommendIslamicFinanceShariahOutcomeRequest
        {
            ReviewOutcomeCode = "APPROVED",
            ReviewNotes = "Recommendation captured."
        }, 3);

        var exception = Assert.Throws<InvalidOperationException>(() =>
            shariahService.ApproveOutcome(created.Id, 3));

        Assert.Contains("maker-checker", exception.Message, StringComparison.OrdinalIgnoreCase);
    }
}
