using CashLineERP.Application.Pricing;
using CashLineERP.Application.Sales;
using CashLineERP.Contracts.Pricing;
using CashLineERP.Contracts.Sales;
using CashLineERP.Infrastructure.Persistence.Repositories;

namespace CashLineERP.Api.Tests;

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

        var pricingService = new PricingRuleService(new PricingRuleRepository(dbContext));

        var createdRule = pricingService.CreatePricingRule(new CreatePricingRuleRequest(
            RuleName: "Customer 2 item 1001 May price",
            BranchId: 1,
            CustomerId: 2,
            ItemId: 1001,
            CurrencyCode: "EGP",
            UnitOfMeasureCode: "EA",
            MinimumQuantity: 5m,
            MaximumQuantity: null,
            FixedUnitPrice: 29m,
            Priority: 100,
            EffectiveFromDate: new DateOnly(2026, 5, 1),
            EffectiveToDate: new DateOnly(2026, 5, 31),
            Notes: "Wave 3 pricing baseline rule"));

        Assert.Equal("DRAFT", createdRule.StatusCode);
        Assert.False(createdRule.IsActive);

        var submittedRule = pricingService.SubmitPricingRule(createdRule.PricingRuleId, 2);
        Assert.Equal("SUBMITTED", submittedRule.StatusCode);

        var approvedRule = pricingService.ApprovePricingRule(createdRule.PricingRuleId, 4);
        Assert.Equal("APPROVED", approvedRule.StatusCode);

        var activeRule = pricingService.ActivatePricingRule(createdRule.PricingRuleId, 4);
        Assert.True(activeRule.IsActive);

        var evaluation = pricingService.EvaluatePricing(new PricingEvaluationRequest(
            BranchId: 1,
            CustomerId: 2,
            PricingDate: new DateOnly(2026, 5, 20),
            CurrencyCode: "EGP",
            Lines:
            [
                new PricingEvaluationLineRequest(1001, 8m, "EA", null),
                new PricingEvaluationLineRequest(1002, 3m, "BOX", 41m)
            ]));

        var matchedLine = evaluation.Lines.Single(line => line.ItemId == 1001);
        Assert.Equal("RULE", matchedLine.PricingSourceCode);
        Assert.Equal(29m, matchedLine.AppliedUnitPrice);
        Assert.Equal(activeRule.PricingRuleId, matchedLine.PricingRuleId);

        var manualLine = evaluation.Lines.Single(line => line.ItemId == 1002);
        Assert.Equal("MANUAL", manualLine.PricingSourceCode);
        Assert.Equal(41m, manualLine.AppliedUnitPrice);
    }

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

        var pricingService = new PricingRuleService(new PricingRuleRepository(dbContext));
        var salesOrderService = new SalesOrderService(new SalesOrderRepository(dbContext));

        var activeRule = pricingService.ActivatePricingRule(
            pricingService.ApprovePricingRule(
                pricingService.SubmitPricingRule(
                    pricingService.CreatePricingRule(new CreatePricingRuleRequest(
                        RuleName: "Customer 2 item 1002 boxed price",
                        BranchId: 1,
                        CustomerId: 2,
                        ItemId: 1002,
                        CurrencyCode: "EGP",
                        UnitOfMeasureCode: "BOX",
                        MinimumQuantity: 2m,
                        MaximumQuantity: null,
                        FixedUnitPrice: 44m,
                        Priority: 90,
                        EffectiveFromDate: new DateOnly(2026, 5, 1),
                        EffectiveToDate: new DateOnly(2026, 5, 31),
                        Notes: "Automatic sales-order pricing")).PricingRuleId,
                    2).PricingRuleId,
                4).PricingRuleId,
            4);

        var salesOrder = salesOrderService.CreateSalesOrder(new CreateSalesOrderRequest(
            BranchId: 1,
            CustomerId: 2,
            OrderDate: new DateOnly(2026, 5, 20),
            CurrencyCode: "EGP",
            ExchangeRate: 1m,
            Lines:
            [
                new CreateSalesOrderLineRequest(1002, 1, 3m, "BOX", 0m, "VAT14")
            ]));

        var pricedLine = Assert.Single(salesOrder.Lines);
        Assert.Equal(44m, pricedLine.UnitPrice);
        Assert.Equal("RULE", pricedLine.PricingSourceCode);
        Assert.Equal(activeRule.PricingRuleId, pricedLine.PricingRuleId);
        Assert.Equal(activeRule.RuleCode, pricedLine.PricingRuleCode);
    }
}
