using System.Net;
using System.Net.Http.Json;
using System.Text.Json;

namespace GerbilManager.Tests;

/// <summary>LITTER-MORTALITY: deathsWithin8Weeks field — round-trip, validation, null default.</summary>
public class LitterMortalityTests : IClassFixture<ApiFactory>
{
    private readonly HttpClient _client;
    public LitterMortalityTests(ApiFactory factory) => _client = factory.CreateClient();

    private static int? GetInt(JsonElement el, string prop) =>
        el.TryGetProperty(prop, out var v) && v.ValueKind == JsonValueKind.Number
            ? v.GetInt32() : null;

    private async Task<JsonElement> CreateAndGet(object body)
    {
        var post = await _client.PostAsJsonAsync("/litters", body);
        post.EnsureSuccessStatusCode();
        var idStr = JsonDocument.Parse(await post.Content.ReadAsStringAsync()).RootElement
            .GetProperty("id").GetString()!;
        return JsonDocument.Parse(await _client.GetStringAsync($"/litters/{idStr}")).RootElement;
    }

    [Fact]
    public async Task DeathsWithin8Weeks_round_trips()
    {
        var el = await CreateAndGet(new
        {
            name = "Wurf Mortalitätstest",
            date = "2026-05-01",
            totalBorn = 6,
            deathsWithin8Weeks = 2,
        });
        Assert.Equal(6, GetInt(el, "totalBorn"));
        Assert.Equal(2, GetInt(el, "deathsWithin8Weeks"));
    }

    [Fact]
    public async Task DeathsWithin8Weeks_defaults_null()
    {
        var el = await CreateAndGet(new { name = "Wurf Kein Mort", date = "2026-05-02" });
        Assert.True(el.TryGetProperty("deathsWithin8Weeks", out var v));
        Assert.Equal(JsonValueKind.Null, v.ValueKind);
    }

    [Fact]
    public async Task DeathsWithin8Weeks_exceeding_TotalBorn_returns_400()
    {
        var resp = await _client.PostAsJsonAsync("/litters", new
        {
            name = "Ungültig",
            date = "2026-05-03",
            totalBorn = 4,
            deathsWithin8Weeks = 5,
        });
        Assert.Equal(HttpStatusCode.BadRequest, resp.StatusCode);
        var body = await resp.Content.ReadAsStringAsync();
        Assert.Contains("TotalBorn", body);
    }

    [Fact]
    public async Task Negative_DeathsWithin8Weeks_returns_400()
    {
        var resp = await _client.PostAsJsonAsync("/litters", new
        {
            name = "Negativ",
            date = "2026-05-04",
            deathsWithin8Weeks = -1,
        });
        Assert.Equal(HttpStatusCode.BadRequest, resp.StatusCode);
        var body = await resp.Content.ReadAsStringAsync();
        Assert.Contains("negativ", body);
    }

    [Fact]
    public async Task DeathsWithin8Weeks_allowed_when_TotalBorn_null()
    {
        var el = await CreateAndGet(new
        {
            name = "Kein TotalBorn",
            date = "2026-05-05",
            deathsWithin8Weeks = 3,
        });
        Assert.Equal(3, GetInt(el, "deathsWithin8Weeks"));
    }
}
