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

namespace CashLineERP.Api.Tests;

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

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

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

        var createResponse = await _client.PostAsJsonAsync("/api/v1/inventory/adjustments", new CreateInventoryAdjustmentRequest(
            BranchId: 1,
            WarehouseId: 1,
            AdjustmentDate: new DateOnly(2026, 5, 6),
            ReasonCode: "COUNT_VARIANCE",
            Notes: "HTTP inventory adjustment flow.",
            Lines:
            [
                new CreateInventoryAdjustmentLineRequest(1001, null, 3m, "EA", 20m, "AVAILABLE", "HTTP-ADJ-GAIN-1", null, "Gain"),
                new CreateInventoryAdjustmentLineRequest(1002, null, -1m, "BOX", 45m, "AVAILABLE", "HTTP-ADJ-LOSS-1", null, "Loss")
            ]));

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

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

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

        await _client.AuthenticateAsFinanceCheckerAsync();

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

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

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

        var getResponse = await _client.GetAsync($"/api/v1/inventory/adjustments/{created.InventoryAdjustmentId}");
        Assert.True(getResponse.IsSuccessStatusCode, await getResponse.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 == "ADJUSTMENT_GAIN" && movement.QuantityMoved == 3m);
        Assert.Contains(movements!, movement => movement.MovementType == "ADJUSTMENT_LOSS" && movement.QuantityMoved == 1m);

        var glResponse = await _client.GetAsync("/api/v1/finance/gl-batches");
        Assert.True(glResponse.IsSuccessStatusCode, await glResponse.Content.ReadAsStringAsync());
        var batches = await glResponse.Content.ReadFromJsonAsync<List<GeneralLedgerBatchResponse>>();
        Assert.NotNull(batches);
        Assert.Contains(batches!, batch => batch.BatchType == "INV_ADJUSTMENT" && batch.SourceDocumentId == created.InventoryAdjustmentId);
    }
}
