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

namespace CashLineERP.Api.Tests;

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

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

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

        var createResponse = await _client.PostAsJsonAsync("/api/v1/inventory/replenishment-rules", new CreateReplenishmentRuleRequest(
            RuleName: "HTTP replenishment rule for warehouse 2",
            BranchId: 1,
            TargetWarehouseId: 2,
            PreferredSourceWarehouseId: 1,
            ItemId: 1001,
            UnitOfMeasureCode: "EA",
            ReorderPointQuantity: 10m,
            TargetSafetyStockQuantity: 15m,
            TargetStockQuantity: 20m,
            SourceSafetyStockQuantity: 20m,
            Priority: 110,
            EffectiveFromDate: new DateOnly(2026, 5, 1),
            EffectiveToDate: new DateOnly(2026, 5, 31),
            Notes: "HTTP replenishment baseline"));
        Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);

        var createdRule = await createResponse.Content.ReadFromJsonAsync<ReplenishmentRuleResponse>();
        Assert.NotNull(createdRule);

        var submitResponse = await _client.PostAsync($"/api/v1/inventory/replenishment-rules/{createdRule!.ReplenishmentRuleId}/submit", null);
        Assert.Equal(HttpStatusCode.OK, submitResponse.StatusCode);

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

        await _client.AuthenticateAsFinanceCheckerAsync();

        var approveResponse = await _client.PostAsync($"/api/v1/inventory/replenishment-rules/{createdRule.ReplenishmentRuleId}/approve", null);
        Assert.Equal(HttpStatusCode.OK, approveResponse.StatusCode);

        var activateResponse = await _client.PostAsync($"/api/v1/inventory/replenishment-rules/{createdRule.ReplenishmentRuleId}/activate", null);
        Assert.Equal(HttpStatusCode.OK, activateResponse.StatusCode);

        await _client.AuthenticateAsInternalAsync();

        var evaluateResponse = await _client.PostAsJsonAsync("/api/v1/inventory/replenishment-rules/evaluate", new ReplenishmentEvaluationRequest(
            BranchId: 1,
            AsOfDate: new DateOnly(2026, 5, 21),
            TargetWarehouseId: 2,
            ItemId: 1001));
        Assert.Equal(HttpStatusCode.OK, evaluateResponse.StatusCode);

        var evaluation = await evaluateResponse.Content.ReadFromJsonAsync<ReplenishmentEvaluationResponse>();
        Assert.NotNull(evaluation);

        var line = Assert.Single(evaluation!.Lines);
        Assert.Equal(createdRule.ReplenishmentRuleId, line.ReplenishmentRuleId);
        Assert.Equal(1, line.SourceWarehouseId);
        Assert.Equal(15m, line.TargetSafetyStockQuantity);
        Assert.Equal("REPLENISHMENT_REQUIRED", line.RecommendationStatusCode);
        Assert.True(line.RecommendedTransferQuantity > 0m);

        var planResponse = await _client.PostAsJsonAsync("/api/v1/inventory/replenishment-rules/plan", new ReorderPlanningRequest(
            BranchId: 1,
            AsOfDate: new DateOnly(2026, 5, 21),
            TargetWarehouseId: 2,
            ItemId: 1001));
        Assert.Equal(HttpStatusCode.OK, planResponse.StatusCode);

        var planning = await planResponse.Content.ReadFromJsonAsync<ReorderPlanningResponse>();
        Assert.NotNull(planning);
        var planningLine = Assert.Single(planning!.Lines);
        Assert.Equal(createdRule.ReplenishmentRuleId, planningLine.ReplenishmentRuleId);
        Assert.True(planningLine.IsBelowReorderPoint);
        Assert.True(planningLine.IsBelowSafetyStock);
        Assert.Equal("REPLENISH_TRANSFER", planningLine.PlanningActionCode);
        Assert.True(planningLine.RecommendedReorderQuantity > 0m);
        Assert.True(planningLine.RecommendedTransferQuantity > 0m);
    }
}
