using System.Net;
using System.Net.Http.Json;
using NeonSprawl.Server.Game.AbilityInput;
using NeonSprawl.Server.Tests.Game.PositionState;
using Npgsql;
using Xunit;

namespace NeonSprawl.Server.Tests.Game.AbilityInput;

[Collection("Postgres integration")]
public sealed class HotbarLoadoutPersistenceIntegrationTests(PostgresIntegrationHarness harness)
{
    private PostgresWebApplicationFactory Factory => harness.Factory;

    [RequirePostgresFact]
    public async Task PostThenGetAcrossNewFactory_ShouldPersistHotbarBindings()
    {
        // Arrange
        await ResetHotbarTableAsync();
        var update = new HotbarLoadoutUpdateRequest
        {
            SchemaVersion = HotbarLoadoutUpdateRequest.CurrentSchemaVersion,
            Slots =
            [
                new HotbarSlotBindingJson
                {
                    SlotIndex = 1,
                    AbilityId = PrototypeAbilityRegistry.PrototypePulse,
                },
                new HotbarSlotBindingJson
                {
                    SlotIndex = 4,
                    AbilityId = PrototypeAbilityRegistry.PrototypeGuard,
                },
            ],
        };
        HttpStatusCode postStatus;

        // Act
        using (var firstClient = Factory.CreateClient())
        {
            var post = await firstClient.PostAsJsonAsync(
                "/game/players/dev-local-1/hotbar-loadout",
                update);
            postStatus = post.StatusCode;
        }

        // Assert
        await using var secondFactory = new PostgresWebApplicationFactory();
        using var secondClient = secondFactory.CreateClient();
        var loadout = await secondClient.GetFromJsonAsync<HotbarLoadoutResponse>(
            "/game/players/dev-local-1/hotbar-loadout");
        Assert.Equal(HttpStatusCode.OK, postStatus);
        Assert.NotNull(loadout);
        Assert.Equal(PrototypeAbilityRegistry.PrototypePulse, loadout!.Slots[1].AbilityId);
        Assert.Equal(PrototypeAbilityRegistry.PrototypeGuard, loadout.Slots[4].AbilityId);
    }

    private static async Task ResetHotbarTableAsync()
    {
        var cs = Environment.GetEnvironmentVariable("ConnectionStrings__NeonSprawl");
        if (string.IsNullOrWhiteSpace(cs))
        {
            throw new InvalidOperationException("ConnectionStrings__NeonSprawl is not set.");
        }

        var ddlPath = Path.Combine(AppContext.BaseDirectory, "db", "migrations", "V002__player_hotbar_loadout.sql");
        if (!File.Exists(ddlPath))
        {
            throw new FileNotFoundException($"Test DDL not found at '{ddlPath}'.", ddlPath);
        }

        var ddl = await File.ReadAllTextAsync(ddlPath);
        await using var conn = new NpgsqlConnection(cs);
        await conn.OpenAsync();
        await using (var apply = new NpgsqlCommand(ddl, conn))
        {
            await apply.ExecuteNonQueryAsync();
        }

        await using (var truncate = new NpgsqlCommand("TRUNCATE player_hotbar_loadout;", conn))
        {
            await truncate.ExecuteNonQueryAsync();
        }
    }
}
