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

namespace CashLineERP.Api.Tests;

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

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

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

        var createResponse = await _client.PostAsJsonAsync("/api/v1/inventory/status-controls", new CreateInventoryStatusControlRequest(
            BranchId: 1,
            WarehouseId: 1,
            ControlDate: new DateOnly(2026, 5, 24),
            ReasonCode: "QUALITY_REVIEW",
            Notes: "HTTP stock-status control",
            Lines:
            [
                new CreateInventoryStatusControlLineRequest(1001, null, 2m, "EA", 24m, "AVAILABLE", "QUARANTINE", "BATCH-1001-A", null, null, "Quality hold"),
                new CreateInventoryStatusControlLineRequest(1001, null, 1m, "EA", 24m, "AVAILABLE", "DAMAGED", "BATCH-1001-A", null, null, "Damaged on inspection"),
                new CreateInventoryStatusControlLineRequest(1001, null, 1m, "EA", 24m, "AVAILABLE", "EXPIRED", "BATCH-1001-A", null, new DateOnly(2026, 5, 20), "Expired stock")
            ]));

        Assert.True(createResponse.IsSuccessStatusCode, await createResponse.Content.ReadAsStringAsync());
        var created = await createResponse.Content.ReadFromJsonAsync<InventoryStatusControlResponse>();
        Assert.NotNull(created);

        var submitResponse = await _client.PostAsync($"/api/v1/inventory/status-controls/{created!.InventoryStatusControlId}/submit", null);
        Assert.True(submitResponse.IsSuccessStatusCode, await submitResponse.Content.ReadAsStringAsync());

        var prematurePostResponse = await _client.PostAsync($"/api/v1/inventory/status-controls/{created.InventoryStatusControlId}/post", null);
        Assert.Equal(HttpStatusCode.BadRequest, prematurePostResponse.StatusCode);

        await _client.AuthenticateAsFinanceCheckerAsync();

        var approveResponse = await _client.PostAsync($"/api/v1/inventory/status-controls/{created.InventoryStatusControlId}/approve", null);
        Assert.True(approveResponse.IsSuccessStatusCode, await approveResponse.Content.ReadAsStringAsync());

        var postResponse = await _client.PostAsync($"/api/v1/inventory/status-controls/{created.InventoryStatusControlId}/post", null);
        Assert.True(postResponse.IsSuccessStatusCode, await postResponse.Content.ReadAsStringAsync());

        var posted = await postResponse.Content.ReadFromJsonAsync<InventoryStatusControlResponse>();
        Assert.NotNull(posted);
        Assert.Equal("POSTED", posted!.StatusCode);

        var detailResponse = await _client.GetAsync($"/api/v1/inventory/status-controls/{created.InventoryStatusControlId}");
        Assert.True(detailResponse.IsSuccessStatusCode, await detailResponse.Content.ReadAsStringAsync());

        var movementsResponse = await _client.GetAsync("/api/v1/inventory/movements");
        Assert.True(movementsResponse.IsSuccessStatusCode, await movementsResponse.Content.ReadAsStringAsync());
        var movements = await movementsResponse.Content.ReadFromJsonAsync<List<InventoryMovementResponse>>();
        Assert.NotNull(movements);
        Assert.Contains(movements!, movement => movement.MovementType == "STATUS_RECLASS_IN" && movement.StockStatus == "QUARANTINE" && movement.QuantityMoved == 2m);
        Assert.Contains(movements, movement => movement.MovementType == "STATUS_RECLASS_IN" && movement.StockStatus == "DAMAGED" && movement.QuantityMoved == 1m);
        Assert.Contains(movements, movement => movement.MovementType == "STATUS_RECLASS_IN" && movement.StockStatus == "EXPIRED" && movement.QuantityMoved == 1m);

        var traceabilityResponse = await _client.GetAsync("/api/v1/inventory/traceability/lots/BATCH-1001-A");
        Assert.True(traceabilityResponse.IsSuccessStatusCode, await traceabilityResponse.Content.ReadAsStringAsync());
        var traceability = await traceabilityResponse.Content.ReadFromJsonAsync<InventoryTraceabilityResponse>();
        Assert.NotNull(traceability);
        Assert.Contains(traceability!.Positions, position => position.StockStatus == "QUARANTINE" && position.NetQuantity >= 2m);
        Assert.Contains(traceability.Positions, position => position.StockStatus == "DAMAGED" && position.NetQuantity >= 1m);
        Assert.Contains(traceability.Positions, position => position.StockStatus == "EXPIRED" && position.NetQuantity >= 1m);
    }
}
