using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using GameList.Domain;
using GameList.Tests.Support;

namespace GameList.Tests;

public class StateTests
{
    [Fact]
    public async Task Cannot_advance_to_results_when_locked()
    {
        using var factory = new TestWebApplicationFactory();
        var client = factory.CreateClientWithCookies();
        await client.RegisterAsync("player");

        var toVote = await client.PostAsync("/api/me/phase/next", JsonContent.Create(new { }));
        toVote.EnsureSuccessStatusCode();

        var toResults = await client.PostAsync("/api/me/phase/next", JsonContent.Create(new { }));

        Assert.Equal(HttpStatusCode.BadRequest, toResults.StatusCode);
    }

    [Fact]
    public async Task Admin_opening_results_moves_players_to_results_phase()
    {
        using var factory = new TestWebApplicationFactory();
        var admin = factory.CreateClientWithCookies();
        await admin.RegisterAsync("admin", admin: true);

        var player = factory.CreateClientWithCookies();
        await player.RegisterAsync("user");

        var toggle = await admin.PostAsJsonAsync("/api/admin/results", new { resultsOpen = true });
        toggle.EnsureSuccessStatusCode();

        var state = await player.GetFromJsonAsync<JsonElement>("/api/state");

        Assert.Equal(Phase.Results.ToString(), state.GetProperty("currentPhase").GetString());
        Assert.True(state.GetProperty("resultsOpen").GetBoolean());
    }

    [Fact]
    public async Task Name_endpoint_trims_and_rejects_blank()
    {
        using var factory = new TestWebApplicationFactory();
        var client = factory.CreateClientWithCookies();
        await client.RegisterAsync("nametest");

        var bad = await client.PostAsJsonAsync("/api/me/name", new { name = "   " });
        Assert.Equal(HttpStatusCode.BadRequest, bad.StatusCode);

        var ok = await client.PostAsJsonAsync("/api/me/name", new { name = "  Alice  " });
        ok.EnsureSuccessStatusCode();
        var me = await client.GetFromJsonAsync<JsonElement>("/api/me");
        Assert.Equal("Alice", me.GetProperty("displayName").GetString());
    }

    [Fact]
    public async Task Phase_prev_admin_only()
    {
        using var factory = new TestWebApplicationFactory();
        var player = factory.CreateClientWithCookies();
        await player.RegisterAsync("phase");

        var notAdmin = await player.PostAsJsonAsync("/api/me/phase/prev", new { });
        Assert.Equal(HttpStatusCode.BadRequest, notAdmin.StatusCode);

        var admin = factory.CreateClientWithCookies();
        await admin.RegisterAsync("admin", admin: true);
        await admin.PostAsJsonAsync("/api/me/phase/next", new { }); // to Vote
        var back = await admin.PostAsJsonAsync("/api/me/phase/prev", new { });
        back.EnsureSuccessStatusCode();
        var me = await admin.GetFromJsonAsync<JsonElement>("/api/me");
        Assert.Equal(Phase.Suggest.ToString(), me.GetProperty("currentPhase").GetString());
    }

    [Fact]
    public async Task State_endpoint_requires_auth_and_counts()
    {
        using var factory = new TestWebApplicationFactory();
        var anon = factory.CreateClient();
        var unauthorized = await anon.GetAsync("/api/state");
        Assert.NotEqual(HttpStatusCode.OK, unauthorized.StatusCode);

        var client = factory.CreateClientWithCookies();
        await client.RegisterAsync("counting");
        await client.CreateSuggestionAsync("One");
        var state = await client.GetFromJsonAsync<JsonElement>("/api/state");
        Assert.True(state.TryGetProperty("Players", out var players) || state.TryGetProperty("players", out players));
        Assert.True(players.GetInt32() >= 1);
        Assert.True(state.TryGetProperty("Suggestions", out var suggestions) || state.TryGetProperty("suggestions", out suggestions));
        Assert.True(suggestions.GetInt32() >= 1);
    }

    [Fact]
    public async Task Health_endpoint_ok()
    {
        using var factory = new TestWebApplicationFactory();
        var resp = await factory.CreateClient().GetFromJsonAsync<JsonElement>("/health");
        Assert.Equal("ok", resp.GetProperty("status").GetString());
    }
}
