using Dapper;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using Testcontainers.PostgreSql;
using WorkClub.Infrastructure.Data;

namespace WorkClub.Tests.Integration.Data;

public class MigrationTests : IAsyncLifetime
{
    private PostgreSqlContainer? _container;
    private string? _connectionString;

    public async Task InitializeAsync()
    {
        _container = new PostgreSqlBuilder()
            .WithImage("postgres:16-alpine")
            .Build();

        await _container.StartAsync();
        _connectionString = _container.GetConnectionString();
    }

    public async Task DisposeAsync()
    {
        if (_container != null)
        {
            await _container.DisposeAsync();
        }
    }

    [Fact]
    public async Task Migration_AppliesSuccessfully_CreatesAllTables()
    {
        // Arrange
        var options = new DbContextOptionsBuilder<AppDbContext>()
            .UseNpgsql(_connectionString)
            .Options;

        // Act
        await using var context = new AppDbContext(options);
        await context.Database.MigrateAsync();

        // Assert - verify all expected tables exist
        await using var connection = new NpgsqlConnection(_connectionString);
        var tables = (await connection.QueryAsync<string>(
            @"SELECT table_name 
              FROM information_schema.tables 
              WHERE table_schema = 'public' 
              ORDER BY table_name")).ToList();

        Assert.Contains("clubs", tables);
        Assert.Contains("members", tables);
        Assert.Contains("work_items", tables);
        Assert.Contains("shifts", tables);
        Assert.Contains("shift_signups", tables);
    }

    [Fact]
    public async Task Migration_CreatesCorrectIndexes()
    {
        // Arrange
        var options = new DbContextOptionsBuilder<AppDbContext>()
            .UseNpgsql(_connectionString)
            .Options;

        // Act
        await using var context = new AppDbContext(options);
        await context.Database.MigrateAsync();

        // Assert - verify critical indexes exist
        await using var connection = new NpgsqlConnection(_connectionString);
        var indexes = (await connection.QueryAsync<string>(
            @"SELECT indexname 
              FROM pg_indexes 
              WHERE schemaname = 'public' 
              ORDER BY indexname")).ToList();

        // TenantId indexes
        Assert.Contains(indexes, i => i.Contains("tenant_id"));

        // ClubId indexes
        Assert.Contains(indexes, i => i.Contains("club_id"));

        // Status indexes for WorkItem
        Assert.Contains(indexes, i => i.Contains("status"));
    }

    [Fact]
    public async Task Migration_CreatesExpectedSchema()
    {
        // Arrange
        var options = new DbContextOptionsBuilder<AppDbContext>()
            .UseNpgsql(_connectionString)
            .Options;

        // Act
        await using var context = new AppDbContext(options);
        await context.Database.MigrateAsync();

        // Assert - verify schema integrity (RLS and policies are applied via SeedDataService, not migrations)
        await using var connection = new NpgsqlConnection(_connectionString);
        
        // Verify tenant_id columns exist on all tables
        var tenantColumns = (await connection.QueryAsync<string>(
            @"SELECT table_name 
              FROM information_schema.columns 
              WHERE table_schema = 'public' 
              AND column_name = 'TenantId' 
              ORDER BY table_name")).ToList();

        Assert.Contains("clubs", tenantColumns);
        Assert.Contains("members", tenantColumns);
        Assert.Contains("work_items", tenantColumns);
        Assert.Contains("shifts", tenantColumns);
        Assert.Contains("shift_signups", tenantColumns);
    }
}
