using System.Net;
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 DataQualityTests
{
private readonly ApiFactory _factory;
public DataQualityTests(ApiFactory factory) => _factory = factory;
private async Task QuickProductAsync(ApiActor api, string name, decimal? price = null)
{
var r = await api.Http.PostAsJsonAsync("/api/catalog/products/quick", new { name, salePrice = price });
r.StatusCode.Should().Be(HttpStatusCode.Created, await r.Content.ReadAsStringAsync());
return (await r.Content.ReadFromJsonAsync()).GetProperty("id").GetString()!;
}
[Fact]
public async Task Counts_detail_bulkfix_and_dismiss_work()
{
var api = new ApiActor(_factory.CreateClient());
await api.SignupAndLoginAsync($"dq-{Guid.NewGuid():N}");
// Товары с проблемами: без цены (и в корне → без группы), + дубль по имени.
var p1 = await QuickProductAsync(api, "Молоко разливное"); // нет цены, корень
await QuickProductAsync(api, "Хлеб белый", 180m); // есть цена, но корень
await QuickProductAsync(api, "Дубль-товар");
await QuickProductAsync(api, "Дубль-товар"); // пара → dup-name-unit
// Пересчёт → сводка со счётчиками.
var sumResp = await api.Http.PostAsJsonAsync("/api/data-quality/recompute", new { });
sumResp.EnsureSuccessStatusCode();
var sum = await sumResp.Content.ReadFromJsonAsync();
var checks = sum.GetProperty("checks").EnumerateArray()
.ToDictionary(x => x.GetProperty("checkType").GetString()!, x => x.GetProperty("count").GetInt32());
checks["no-group"].Should().BeGreaterThanOrEqualTo(4, "все 4 товара в корневой группе");
checks["no-sale-price"].Should().BeGreaterThanOrEqualTo(3, "три без цены");
checks["dup-name-unit"].Should().BeGreaterThanOrEqualTo(1, "пара «Дубль-товар»");
// Детальный список без цены содержит p1.
var noPrice = await api.ListAsync("/api/data-quality/no-sale-price/products");
noPrice.Should().Contain(x => x.GetProperty("id").GetString() == p1);
// Массовое: задать цену p1 → в списке «без цены» его больше нет.
var setPrice = await api.Http.PostAsJsonAsync("/api/data-quality/bulk/set-price",
new { productIds = new[] { p1 }, priceTypeId = (string?)null, amount = 300m });
setPrice.EnsureSuccessStatusCode();
var noPrice2 = await api.ListAsync("/api/data-quality/no-sale-price/products");
noPrice2.Should().NotContain(x => x.GetProperty("id").GetString() == p1);
// «Это разные товары» для дубля → счётчик дублей падает.
var dupList = await api.ListAsync("/api/data-quality/dup-name-unit/products");
var dupId = dupList.First().GetProperty("id").GetString();
(await api.Http.PostAsJsonAsync("/api/data-quality/dismiss",
new { checkType = "dup-name-unit", productId = dupId, barcode = (string?)null })).EnsureSuccessStatusCode();
var afterResp = await api.Http.PostAsJsonAsync("/api/data-quality/recompute", new { });
afterResp.EnsureSuccessStatusCode();
var afterDismiss = await afterResp.Content.ReadFromJsonAsync();
var dupAfter = afterDismiss.GetProperty("checks").EnumerateArray()
.First(x => x.GetProperty("checkType").GetString() == "dup-name-unit").GetProperty("count").GetInt32();
dupAfter.Should().Be(0, "единственная пара помечена «разные товары»");
}
}