using System.Net;
using System.Net.Http.Json;
using CashLineERP.Contracts.Pricing;
using CashLineERP.Contracts.Sales;

namespace CashLineERP.Api.Tests;

public sealed class PricingRuleEngineQaTests : IClassFixture<ApiTestFactory>
{
    private readonly HttpClient _client;

    public PricingRuleEngineQaTests(ApiTestFactory factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task Pricing_Rule_Endpoints_And_Sales_Order_Consumption_Work_End_To_End()
    {
        await _client.AuthenticateAsInternalAsync();

        var createRuleResponse = await _client.PostAsJsonAsync("/api/v1/sales/pricing-rules", new CreatePricingRuleRequest(
            RuleName: "HTTP price rule for item 1001",
            BranchId: 1,
            CustomerId: 2,
            ItemId: 1001,
            CurrencyCode: "EGP",
            UnitOfMeasureCode: "EA",
            MinimumQuantity: 4m,
            MaximumQuantity: null,
            FixedUnitPrice: 27m,
            Priority: 120,
            EffectiveFromDate: new DateOnly(2026, 5, 1),
            EffectiveToDate: new DateOnly(2026, 5, 31),
            Notes: "HTTP pricing baseline"));
        Assert.Equal(HttpStatusCode.OK, createRuleResponse.StatusCode);

        var createdRule = await createRuleResponse.Content.ReadFromJsonAsync<PricingRuleResponse>();
        Assert.NotNull(createdRule);

        var submitRuleResponse = await _client.PostAsync($"/api/v1/sales/pricing-rules/{createdRule!.PricingRuleId}/submit", null);
        Assert.Equal(HttpStatusCode.OK, submitRuleResponse.StatusCode);

        await _client.AuthenticateAsFinanceCheckerAsync();

        var approveRuleResponse = await _client.PostAsync($"/api/v1/sales/pricing-rules/{createdRule.PricingRuleId}/approve", null);
        Assert.Equal(HttpStatusCode.OK, approveRuleResponse.StatusCode);

        var activateRuleResponse = await _client.PostAsync($"/api/v1/sales/pricing-rules/{createdRule.PricingRuleId}/activate", null);
        Assert.Equal(HttpStatusCode.OK, activateRuleResponse.StatusCode);

        var activeRule = await activateRuleResponse.Content.ReadFromJsonAsync<PricingRuleResponse>();
        Assert.NotNull(activeRule);
        Assert.True(activeRule!.IsActive);

        await _client.AuthenticateAsInternalAsync();

        var evaluateResponse = await _client.PostAsJsonAsync("/api/v1/sales/pricing-rules/evaluate", new PricingEvaluationRequest(
            BranchId: 1,
            CustomerId: 2,
            PricingDate: new DateOnly(2026, 5, 21),
            CurrencyCode: "EGP",
            Lines:
            [
                new PricingEvaluationLineRequest(1001, 6m, "EA", null)
            ]));
        Assert.Equal(HttpStatusCode.OK, evaluateResponse.StatusCode);

        var evaluation = await evaluateResponse.Content.ReadFromJsonAsync<PricingEvaluationResponse>();
        Assert.NotNull(evaluation);
        var evaluatedLine = Assert.Single(evaluation!.Lines);
        Assert.Equal("RULE", evaluatedLine.PricingSourceCode);
        Assert.Equal(27m, evaluatedLine.AppliedUnitPrice);

        var createSalesOrderResponse = await _client.PostAsJsonAsync("/api/v1/sales/orders", new CreateSalesOrderRequest(
            BranchId: 1,
            CustomerId: 2,
            OrderDate: new DateOnly(2026, 5, 21),
            CurrencyCode: "EGP",
            ExchangeRate: 1m,
            Lines:
            [
                new CreateSalesOrderLineRequest(1001, 1, 6m, "EA", 0m, "VAT14")
            ]));
        Assert.Equal(HttpStatusCode.OK, createSalesOrderResponse.StatusCode);

        var salesOrder = await createSalesOrderResponse.Content.ReadFromJsonAsync<SalesOrderResponse>();
        Assert.NotNull(salesOrder);
        var pricedLine = Assert.Single(salesOrder!.Lines);
        Assert.Equal("RULE", pricedLine.PricingSourceCode);
        Assert.Equal(27m, pricedLine.UnitPrice);
        Assert.Equal(activeRule.PricingRuleId, pricedLine.PricingRuleId);
        Assert.Equal(activeRule.RuleCode, pricedLine.PricingRuleCode);
    }
}
