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

namespace CashLineERP.Api.Tests;

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

        var salesOrderService = new SalesOrderService(new SalesOrderRepository(dbContext));
        var internalWorkbenchService = new InternalWorkbenchService(new InternalWorkbenchRepository(dbContext));

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

        var salesOrderLine = Assert.Single(salesOrder.Lines);
        Assert.Equal(50m, salesOrderLine.UnitPrice);
        Assert.Equal(50m, salesOrderLine.BaseUnitPrice);

        var discountOverride = salesOrderService.CreateDiscountOverride(
            salesOrder.SalesOrderId,
            2,
            new CreateSalesDiscountOverrideRequest(
                SalesOrderLineId: salesOrderLine.SalesOrderLineId,
                RequestedUnitPrice: 42m,
                ReasonCode: "MANAGER_APPROVAL",
                Notes: "Commercial discount for key account retention."));

        Assert.Equal("SUBMITTED", discountOverride.StatusCode);
        Assert.Equal(24m, discountOverride.RequestedDiscountAmount);
        Assert.Equal(16m, discountOverride.RequestedDiscountPercent);

        var approvalQueue = internalWorkbenchService.GetApprovalQueue("SALES");
        Assert.Contains(approvalQueue, item =>
            item.DocumentType == "DISCOUNT_OVERRIDE"
            && item.DocumentId == discountOverride.SalesDiscountOverrideId
            && item.DocumentNumber == discountOverride.OverrideNumber);

        var selfApprovalException = Assert.Throws<InvalidOperationException>(() =>
            salesOrderService.ApproveDiscountOverride(
                salesOrder.SalesOrderId,
                2,
                new ReviewSalesDiscountOverrideRequest("Maker cannot approve own discount request."),
                discountOverride.SalesDiscountOverrideId));
        Assert.Contains("self-approval", selfApprovalException.Message, StringComparison.OrdinalIgnoreCase);

        var approvedOverride = salesOrderService.ApproveDiscountOverride(
            salesOrder.SalesOrderId,
            4,
            new ReviewSalesDiscountOverrideRequest("Approved by finance checker."),
            discountOverride.SalesDiscountOverrideId);

        Assert.Equal("APPROVED", approvedOverride.StatusCode);
        Assert.Equal("APPROVED", approvedOverride.DecisionCode);

        var updatedOrder = salesOrderService.GetSalesOrder(salesOrder.SalesOrderId);
        Assert.NotNull(updatedOrder);

        var updatedLine = Assert.Single(updatedOrder!.Lines);
        Assert.Equal(42m, updatedLine.UnitPrice);
        Assert.Equal(50m, updatedLine.BaseUnitPrice);
        Assert.Equal(24m, updatedLine.DiscountAmount);
        Assert.Equal(16m, updatedLine.DiscountPercent);
        Assert.Equal(discountOverride.SalesDiscountOverrideId, updatedLine.DiscountOverrideId);
        Assert.Equal("OVERRIDE_APPROVED", updatedLine.DiscountSourceCode);
    }

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

        var salesOrderService = new SalesOrderService(new SalesOrderRepository(dbContext));

        var salesOrder = salesOrderService.CreateSalesOrder(new CreateSalesOrderRequest(
            BranchId: 1,
            CustomerId: 2,
            OrderDate: new DateOnly(2026, 5, 23),
            CurrencyCode: "EGP",
            ExchangeRate: 1m,
            Lines:
            [
                new CreateSalesOrderLineRequest(1001, 1, 2m, "EA", 40m, "VAT14")
            ]));

        var salesOrderLine = Assert.Single(salesOrder.Lines);

        var discountOverride = salesOrderService.CreateDiscountOverride(
            salesOrder.SalesOrderId,
            2,
            new CreateSalesDiscountOverrideRequest(
                SalesOrderLineId: salesOrderLine.SalesOrderLineId,
                RequestedUnitPrice: 36m,
                ReasonCode: "EXCEPTION_REQUEST",
                Notes: "Requested discount requires finance review."));

        var rejectedOverride = salesOrderService.RejectDiscountOverride(
            salesOrder.SalesOrderId,
            4,
            new ReviewSalesDiscountOverrideRequest("Rejected due to insufficient commercial justification."),
            discountOverride.SalesDiscountOverrideId);

        Assert.Equal("REJECTED", rejectedOverride.StatusCode);
        Assert.Equal("REJECTED", rejectedOverride.DecisionCode);

        var currentOrder = salesOrderService.GetSalesOrder(salesOrder.SalesOrderId);
        Assert.NotNull(currentOrder);
        var currentLine = Assert.Single(currentOrder!.Lines);
        Assert.Equal(40m, currentLine.UnitPrice);
        Assert.Null(currentLine.DiscountOverrideId);
        Assert.Equal("NONE", currentLine.DiscountSourceCode);
    }
}
