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

namespace CashLineERP.Api.Tests;

public sealed class WalletRuleEngineServiceQaTests
{
    [Fact]
    public void Wallet_Rule_Evaluation_Prefers_More_Specific_Active_Approved_Rule()
    {
        using var dbContext = QaDbContextFactory.CreateContext();
        var walletRuleService = new WalletRuleService(new WalletRuleRepository(dbContext));

        var genericRule = walletRuleService.CreateWalletRule(new CreateWalletRuleRequest(
            RuleName: "Generic Paymob collection",
            BranchId: null,
            PartyTypeCode: "ANY",
            TransactionTypeCode: "COLLECTION",
            WalletSchemeCode: "MOBILE_WALLET",
            IntegrationProviderCode: "PAYMOB",
            CurrencyCode: "EGP",
            MinimumAmount: 0m,
            MaximumAmount: 5000m,
            SettlementLeadDays: 2,
            FeePercent: 1.50m,
            FlatFeeAmount: 2m,
            Priority: 10,
            EffectiveFromDate: new DateOnly(2026, 4, 1),
            EffectiveToDate: null,
            Notes: "Generic collection rule"));

        walletRuleService.SubmitWalletRule(genericRule.WalletRuleId, 3);
        walletRuleService.ApproveWalletRule(genericRule.WalletRuleId, 4);
        walletRuleService.ActivateWalletRule(genericRule.WalletRuleId, 4);

        var branchRule = walletRuleService.CreateWalletRule(new CreateWalletRuleRequest(
            RuleName: "Branch 1 customer Paymob collection",
            BranchId: 1,
            PartyTypeCode: "CUSTOMER",
            TransactionTypeCode: "COLLECTION",
            WalletSchemeCode: "MOBILE_WALLET",
            IntegrationProviderCode: "PAYMOB",
            CurrencyCode: "EGP",
            MinimumAmount: 0m,
            MaximumAmount: 5000m,
            SettlementLeadDays: 1,
            FeePercent: 1.00m,
            FlatFeeAmount: 1m,
            Priority: 10,
            EffectiveFromDate: new DateOnly(2026, 4, 1),
            EffectiveToDate: null,
            Notes: "Branch-specific collection rule"));

        walletRuleService.SubmitWalletRule(branchRule.WalletRuleId, 3);
        walletRuleService.ApproveWalletRule(branchRule.WalletRuleId, 4);
        walletRuleService.ActivateWalletRule(branchRule.WalletRuleId, 4);

        var evaluation = walletRuleService.EvaluateWalletRule(new WalletRuleEvaluationRequest(
            BranchId: 1,
            PartyTypeCode: "CUSTOMER",
            TransactionTypeCode: "COLLECTION",
            WalletSchemeCode: "MOBILE_WALLET",
            CurrencyCode: "EGP",
            RequestedAmount: 100m,
            EvaluationDate: new DateOnly(2026, 4, 5)));

        Assert.Equal(branchRule.WalletRuleId, evaluation.RecommendedWalletRuleId);
        Assert.Equal("PAYMOB", evaluation.RecommendedIntegrationProviderCode);
        Assert.Equal(2, evaluation.Lines.Count);
        Assert.Equal("RECOMMENDED", evaluation.Lines.First().RecommendationStatusCode);
        Assert.Equal(2m, evaluation.Lines.First().EstimatedFeeAmount);
        Assert.Equal(98m, evaluation.Lines.First().EstimatedSettlementAmount);
    }

    [Fact]
    public void Wallet_Rule_Maker_Checker_Blocks_Self_Approval()
    {
        using var dbContext = QaDbContextFactory.CreateContext();
        var walletRuleService = new WalletRuleService(new WalletRuleRepository(dbContext));

        var rule = walletRuleService.CreateWalletRule(new CreateWalletRuleRequest(
            RuleName: "Fawry payout rule",
            BranchId: null,
            PartyTypeCode: "SUPPLIER",
            TransactionTypeCode: "PAYOUT",
            WalletSchemeCode: "MOBILE_WALLET",
            IntegrationProviderCode: "FAWRY",
            CurrencyCode: "EGP",
            MinimumAmount: 50m,
            MaximumAmount: 10000m,
            SettlementLeadDays: 1,
            FeePercent: 0.75m,
            FlatFeeAmount: 1.5m,
            Priority: 5,
            EffectiveFromDate: new DateOnly(2026, 4, 5),
            EffectiveToDate: null,
            Notes: "Supplier payout rule"));

        walletRuleService.SubmitWalletRule(rule.WalletRuleId, 3);

        var exception = Assert.Throws<InvalidOperationException>(() =>
            walletRuleService.ApproveWalletRule(rule.WalletRuleId, 3));

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