using Dapper;
using KArtSell.Host.Infrastructure;
using Npgsql;
using Xunit;

namespace KArtSell.Integration.Tests;

[Collection("Database")]
public class KisConnectionPoolTests : IAsyncLifetime
{
    private readonly NpgsqlDataSource _dataSource;

    public KisConnectionPoolTests(DatabaseFixture fixture)
    {
        _dataSource = fixture.DataSource;
    }

    public async Task InitializeAsync()
    {
        await using var conn = await _dataSource.OpenConnectionAsync();
        await conn.ExecuteAsync("""
            CREATE SCHEMA IF NOT EXISTS kis;
            CREATE TABLE IF NOT EXISTS kis.connection_pool_state (
                id BIGSERIAL PRIMARY KEY,
                connection_id UUID NOT NULL UNIQUE,
                state VARCHAR(50) NOT NULL,
                priority INT NOT NULL,
                token_hash VARCHAR(256),
                expires_at TIMESTAMP WITH TIME ZONE,
                created_at TIMESTAMP WITH TIME ZONE NOT NULL,
                released_at TIMESTAMP WITH TIME ZONE,
                published_at TIMESTAMP WITH TIME ZONE NOT NULL
            );
            CREATE TABLE IF NOT EXISTS kis.token_refresh_log (
                id BIGSERIAL PRIMARY KEY,
                connection_id UUID NOT NULL,
                refresh_at TIMESTAMP WITH TIME ZONE NOT NULL,
                status VARCHAR(50) NOT NULL,
                error_message TEXT,
                new_token_hash VARCHAR(256),
                executed_at TIMESTAMP WITH TIME ZONE NOT NULL,
                published_at TIMESTAMP WITH TIME ZONE NOT NULL
            );
            TRUNCATE kis.connection_pool_state CASCADE;
            TRUNCATE kis.token_refresh_log CASCADE;
            """);
    }

    public Task DisposeAsync() => Task.CompletedTask;

    [Fact]
    public async Task ConnectionPoolSchema_ExistsWithCorrectStructure()
    {
        // Verify kis schema and tables exist
        await using var conn = await _dataSource.OpenConnectionAsync();

        var schemaExists = await conn.QueryFirstOrDefaultAsync<bool>(
            "SELECT EXISTS(SELECT 1 FROM information_schema.schemata WHERE schema_name = 'kis')");
        Assert.True(schemaExists, "kis schema should exist");

        var poolTableExists = await conn.QueryFirstOrDefaultAsync<bool>(
            "SELECT EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema = 'kis' AND table_name = 'connection_pool_state')");
        Assert.True(poolTableExists, "kis.connection_pool_state table should exist");

        var tokenLogExists = await conn.QueryFirstOrDefaultAsync<bool>(
            "SELECT EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema = 'kis' AND table_name = 'token_refresh_log')");
        Assert.True(tokenLogExists, "kis.token_refresh_log table should exist");
    }

    [Fact]
    public async Task ConnectionPoolState_HasRequiredColumns()
    {
        await using var conn = await _dataSource.OpenConnectionAsync();

        var columnNames = await conn.QueryAsync<string>("""
            SELECT column_name
            FROM information_schema.columns
            WHERE table_schema = 'kis' AND table_name = 'connection_pool_state'
            ORDER BY ordinal_position
            """);

        var cols = columnNames.ToList();
        Assert.Contains("connection_id", cols);
        Assert.Contains("state", cols);
        Assert.Contains("priority", cols);
        Assert.Contains("token_hash", cols);
    }

    [Fact]
    public async Task TokenRefreshLog_HasRequiredColumns()
    {
        await using var conn = await _dataSource.OpenConnectionAsync();

        var columnNames = await conn.QueryAsync<string>("""
            SELECT column_name
            FROM information_schema.columns
            WHERE table_schema = 'kis' AND table_name = 'token_refresh_log'
            ORDER BY ordinal_position
            """);

        var cols = columnNames.ToList();
        Assert.Contains("connection_id", cols);
        Assert.Contains("status", cols);
        Assert.Contains("executed_at", cols);
        Assert.Contains("published_at", cols);
    }
}
