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

namespace CashLineERP.Api.Tests;

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

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

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

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

        var salesOrder = await createSalesOrderResponse.Content.ReadFromJsonAsync<SalesOrderResponse>();
        Assert.NotNull(salesOrder);
        var salesOrderLine = Assert.Single(salesOrder!.Lines);

        var createDiscountOverrideResponse = await _client.PostAsJsonAsync(
            $"/api/v1/sales/orders/{salesOrder.SalesOrderId}/discount-overrides",
            new CreateSalesDiscountOverrideRequest(
                SalesOrderLineId: salesOrderLine.SalesOrderLineId,
                RequestedUnitPrice: 41m,
                ReasonCode: "PROMO_EXCEPTION",
                Notes: "One-time approved commercial exception."));
        Assert.Equal(HttpStatusCode.OK, createDiscountOverrideResponse.StatusCode);

        var discountOverride = await createDiscountOverrideResponse.Content.ReadFromJsonAsync<SalesDiscountOverrideResponse>();
        Assert.NotNull(discountOverride);
        Assert.Equal("SUBMITTED", discountOverride!.StatusCode);

        var getOverridesResponse = await _client.GetAsync($"/api/v1/sales/orders/{salesOrder.SalesOrderId}/discount-overrides");
        Assert.Equal(HttpStatusCode.OK, getOverridesResponse.StatusCode);
        var overrides = await getOverridesResponse.Content.ReadFromJsonAsync<IReadOnlyCollection<SalesDiscountOverrideResponse>>();
        Assert.NotNull(overrides);
        Assert.Contains(overrides!, item => item.SalesDiscountOverrideId == discountOverride.SalesDiscountOverrideId);

        var approvalsResponse = await _client.GetAsync("/api/v1/internal/work-queues/approvals?moduleCode=SALES");
        Assert.Equal(HttpStatusCode.OK, approvalsResponse.StatusCode);
        var approvalItems = await approvalsResponse.Content.ReadFromJsonAsync<IReadOnlyCollection<InternalApprovalQueueItemResponse>>();
        Assert.NotNull(approvalItems);
        Assert.Contains(approvalItems!, item =>
            item.DocumentType == "DISCOUNT_OVERRIDE"
            && item.DocumentId == discountOverride.SalesDiscountOverrideId
            && item.DocumentNumber == discountOverride.OverrideNumber);

        await _client.AuthenticateAsFinanceCheckerAsync();

        var approveDiscountOverrideResponse = await _client.PostAsJsonAsync(
            $"/api/v1/sales/orders/{salesOrder.SalesOrderId}/discount-overrides/{discountOverride.SalesDiscountOverrideId}/approve",
            new ReviewSalesDiscountOverrideRequest("Approved for limited commercial retention."));
        Assert.Equal(HttpStatusCode.OK, approveDiscountOverrideResponse.StatusCode);

        var approvedOverride = await approveDiscountOverrideResponse.Content.ReadFromJsonAsync<SalesDiscountOverrideResponse>();
        Assert.NotNull(approvedOverride);
        Assert.Equal("APPROVED", approvedOverride!.StatusCode);

        await _client.AuthenticateAsInternalAsync();

        var getSalesOrderResponse = await _client.GetAsync($"/api/v1/sales/orders/{salesOrder.SalesOrderId}");
        Assert.Equal(HttpStatusCode.OK, getSalesOrderResponse.StatusCode);

        var updatedOrder = await getSalesOrderResponse.Content.ReadFromJsonAsync<SalesOrderResponse>();
        Assert.NotNull(updatedOrder);

        var updatedLine = Assert.Single(updatedOrder!.Lines);
        Assert.Equal(41m, updatedLine.UnitPrice);
        Assert.Equal(48m, updatedLine.BaseUnitPrice);
        Assert.Equal(28m, updatedLine.DiscountAmount);
        Assert.Equal(14.5833m, updatedLine.DiscountPercent);
        Assert.Equal(discountOverride.SalesDiscountOverrideId, updatedLine.DiscountOverrideId);
        Assert.Equal("OVERRIDE_APPROVED", updatedLine.DiscountSourceCode);
    }
}
