using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;

public class ApiFixture : WebApplicationFactory<Program>, IAsyncLifetime
{
    // Override configuration to point at a test database — never run tests against
    // the development database; a botched rollback could corrupt seed data.
    //
    // Defaults assume Postgres/Redis are reachable on the host's loopback address
    // (e.g. `docker compose up -d postgres redis` on a dev machine). CI runners that
    // execute the test step inside its own job container (act_runner's default docker
    // executor) can't reach ports published on the Docker *host* via "localhost" —
    // set CONNECTIONSTRINGS__DEFAULTCONNECTION / REDIS__CONNECTIONSTRING (e.g. to
    // host.docker.internal) in that environment to override.
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseEnvironment("Testing");
        builder.ConfigureAppConfiguration((_, config) =>
        {
            var connectionString = Environment.GetEnvironmentVariable("CONNECTIONSTRINGS__DEFAULTCONNECTION")
                ?? "Host=localhost;Port=5437;Database=vigilcare_records_test;Username=postgres;Password=password";
            var redisConnectionString = Environment.GetEnvironmentVariable("REDIS__CONNECTIONSTRING")
                ?? "localhost:6383,defaultDatabase=1,allowAdmin=true";
            var fhirBaseUrl = Environment.GetEnvironmentVariable("FHIR__BASEURL")
                ?? "http://localhost/fhir";

            config.AddInMemoryCollection(new Dictionary<string, string?>
            {
                ["ConnectionStrings:DefaultConnection"] = connectionString,
                ["Redis:ConnectionString"] = redisConnectionString,
                ["Fhir:BaseUrl"] = fhirBaseUrl
            });
        });
    }

    public async Task InitializeAsync()
    {
        // Apply migrations against the test database on first run
        using var scope = Services.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
        await db.Database.MigrateAsync();

        // Flush the test Redis database (db=1) to avoid cross-test cache pollution
        var redis = scope.ServiceProvider.GetRequiredService<IConnectionMultiplexer>();
        await redis.GetDatabase(1).ExecuteAsync("FLUSHDB");
    }

    public new async Task DisposeAsync()
    {
        await base.DisposeAsync();
    }
}