using System.Net.Http.Json;
using System.Text.Json;
using FluentAssertions;
using foodmarket.IntegrationTests.Support;
using Xunit;

namespace foodmarket.IntegrationTests;

[Collection(ApiCollection.Name)]
public class RetailOversellingTests
{
    private readonly ApiFactory _factory;
    public RetailOversellingTests(ApiFactory factory) => _factory = factory;

    private static string RandomBarcode()
        => string.Concat(Enumerable.Range(0, 13).Select(_ => Random.Shared.Next(0, 10)));

    [Fact]
    public async Task Posting_sale_above_available_stock_is_rejected()
    {
        var api = new ApiActor(_factory.CreateClient());
        await api.SignupAndLoginAsync($"oversell-{Guid.NewGuid():N}");
        var refs = await api.LoadRefsAsync();
        var productId = await api.CreateProductAsync(refs, $"Prod-{Guid.NewGuid():N}", retailPrice: 100m, RandomBarcode());

        // Остатка нет (приёмок не делали). Продаём 5 шт. paidCash покрывает итог,
        // чтобы дойти до проверки остатка (а не упасть на валидации оплаты).
        var draftResp = await api.Http.PostAsJsonAsync("/api/sales/retail", new
        {
            date = DateTime.UtcNow,
            storeId = refs.StoreId,
            retailPointId = (string?)null,
            customerId = (string?)null,
            currencyId = refs.CurrencyId,
            payment = 0,
            paidCash = 500m,
            paidCard = 0m,
            notes = "oversell",
            lines = new[] { new { productId, quantity = 5m, unitPrice = 100m, discount = 0m, vatPercent = 0m } },
        });
        draftResp.EnsureSuccessStatusCode();
        var saleId = (await draftResp.Content.ReadFromJsonAsync<JsonElement>()).GetProperty("id").GetString();

        using var post = await api.Http.PostAsJsonAsync($"/api/sales/retail/{saleId}/post", new { });
        ((int)post.StatusCode).Should().Be(409, "продажа сверх остатка должна блокироваться");
    }

    [Fact]
    public async Task Posting_sale_with_underpayment_is_rejected()
    {
        var api = new ApiActor(_factory.CreateClient());
        await api.SignupAndLoginAsync($"underpay-{Guid.NewGuid():N}");
        var refs = await api.LoadRefsAsync();
        var productId = await api.CreateProductAsync(refs, $"Prod-{Guid.NewGuid():N}", 100m, RandomBarcode());

        // Итог 200, оплачено 100 → недоплата → 400 (до проверки остатка).
        var draftResp = await api.Http.PostAsJsonAsync("/api/sales/retail", new
        {
            date = DateTime.UtcNow, storeId = refs.StoreId, retailPointId = (string?)null,
            customerId = (string?)null, currencyId = refs.CurrencyId,
            payment = 0, paidCash = 100m, paidCard = 0m, notes = "underpay",
            lines = new[] { new { productId, quantity = 2m, unitPrice = 100m, discount = 0m, vatPercent = 0m } },
        });
        draftResp.EnsureSuccessStatusCode();
        var saleId = (await draftResp.Content.ReadFromJsonAsync<JsonElement>()).GetProperty("id").GetString();

        using var post = await api.Http.PostAsJsonAsync($"/api/sales/retail/{saleId}/post", new { });
        ((int)post.StatusCode).Should().Be(400, "недоплата должна блокировать проведение");
    }
}
