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

namespace CashLineERP.Api.Tests;

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

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

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

        var createResponse = await _client.PostAsJsonAsync("/api/v1/inventory/stock-counts", new CreateStockCountRequest(
            BranchId: 1,
            WarehouseId: 1,
            CountDate: new DateOnly(2026, 5, 13),
            CountTypeCode: "CYCLE_COUNT",
            Notes: "HTTP stock count flow.",
            Lines:
            [
                new CreateStockCountLineRequest(1001, null, 6m, 8m, "EA", 24m, "AVAILABLE", "HTTP-CNT-1001-A", null, "Gain"),
                new CreateStockCountLineRequest(1002, null, 4m, 3m, "BOX", 40m, "AVAILABLE", "HTTP-CNT-1002-A", null, "Loss")
            ]));

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

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

        await _client.AuthenticateAsFinanceCheckerAsync();

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

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

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

        var getResponse = await _client.GetAsync($"/api/v1/inventory/stock-counts/{created.StockCountId}");
        Assert.True(getResponse.IsSuccessStatusCode, await getResponse.Content.ReadAsStringAsync());
        var stored = await getResponse.Content.ReadFromJsonAsync<StockCountResponse>();
        Assert.NotNull(stored);
        Assert.Equal(posted.InventoryAdjustmentId, stored!.InventoryAdjustmentId);

        var movementResponse = await _client.GetAsync("/api/v1/inventory/movements");
        Assert.True(movementResponse.IsSuccessStatusCode, await movementResponse.Content.ReadAsStringAsync());
        var movements = await movementResponse.Content.ReadFromJsonAsync<List<InventoryMovementResponse>>();
        Assert.NotNull(movements);
        Assert.Contains(movements!, movement => movement.MovementType == "ADJUSTMENT_GAIN" && movement.QuantityMoved == 2m);
        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_STOCK_COUNT" && batch.SourceDocumentId == created.StockCountId);
    }
}
