using Microsoft.Extensions.Diagnostics.HealthChecks;
using ZB.MOM.WW.Auth.ApiKeys.Sqlite;
using ZB.MOM.WW.MxGateway.Server.Diagnostics;
using ZB.MOM.WW.MxGateway.Tests.Security.Authentication;

namespace ZB.MOM.WW.MxGateway.Tests.Diagnostics;

public sealed class AuthStoreHealthCheckTests
{
    private static AuthSqliteConnectionFactory FactoryFor(string sqlitePath)
    {
        // The shared connection factory targets a database path directly.
        return new AuthSqliteConnectionFactory(sqlitePath);
    }

    /// <summary>The health check reports healthy when the auth store database is reachable.</summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    [Fact]
    public async Task Healthy_WhenStoreReachable()
    {
        // Open a real SQLite file via the health check. TempDatabaseDirectory clears the
        // Microsoft.Data.Sqlite connection pool on dispose before deleting the file; without
        // that the pool keeps the .db handle open and the delete throws "used by another
        // process" on Windows (a latent full-suite flake — the file opens fine on macOS).
        using TempDatabaseDirectory directory = TempDatabaseDirectory.Create("authcheck");
        var check = new AuthStoreHealthCheck(FactoryFor(directory.DatabasePath()));
        var result = await check.CheckHealthAsync(new HealthCheckContext());
        Assert.Equal(HealthStatus.Healthy, result.Status);
    }

    /// <summary>The health check reports unhealthy when the database path cannot be opened.</summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    [Fact]
    public async Task Unhealthy_WhenPathUnusable()
    {
        // A regular file used as a parent directory forces the open to fail.
        var bogus = Path.Combine(Path.GetTempPath(), $"authcheck-{Guid.NewGuid():N}");
        await File.WriteAllTextAsync(bogus, "x");
        try
        {
            var check = new AuthStoreHealthCheck(FactoryFor(Path.Combine(bogus, "store.db")));
            var result = await check.CheckHealthAsync(new HealthCheckContext());
            Assert.Equal(HealthStatus.Unhealthy, result.Status);
        }
        finally { if (File.Exists(bogus)) File.Delete(bogus); }
    }
}
