using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Configuration;

namespace ZB.MOM.WW.OtOpcUa.Configuration.Tests;

/// <summary>
///     Spins up a dedicated test database, applies the EF migrations against it, and exposes a
///     <see cref="SqlConnection"/> factory. Disposed at collection teardown (drops the DB).
///     Gated by the <c>OTOPCUA_CONFIG_TEST_SERVER</c> env var so CI runs can opt in explicitly;
///     local runs default to the shared Docker host's SQL Server on <c>10.100.0.35:14330</c>.
/// </summary>
public sealed class SchemaComplianceFixture : IDisposable
{
    private const string DefaultServer = "10.100.0.35,14330";
    private const string DefaultSaPassword = "OtOpcUaDev_2026!";

    /// <summary>Gets the name of the test database.</summary>
    public string DatabaseName { get; }
    /// <summary>Gets the connection string for the test database.</summary>
    public string ConnectionString { get; }

    /// <summary>Initializes a new instance of the SchemaComplianceFixture class.</summary>
    public SchemaComplianceFixture()
    {
        var server = Environment.GetEnvironmentVariable("OTOPCUA_CONFIG_TEST_SERVER") ?? DefaultServer;
        var saPassword = Environment.GetEnvironmentVariable("OTOPCUA_CONFIG_TEST_SA_PASSWORD") ?? DefaultSaPassword;

        DatabaseName = $"OtOpcUaConfig_Test_{DateTime.UtcNow:yyyyMMddHHmmss}_{Guid.NewGuid():N}";
        ConnectionString =
            $"Server={server};Database={DatabaseName};User Id=sa;Password={saPassword};TrustServerCertificate=True;Encrypt=False;";

        var options = new DbContextOptionsBuilder<OtOpcUaConfigDbContext>()
            .UseSqlServer(ConnectionString)
            .Options;

        using var ctx = new OtOpcUaConfigDbContext(options);
        ctx.Database.Migrate();
    }

    /// <summary>Opens a new SQL connection to the test database.</summary>
    /// <returns>An open SQL connection.</returns>
    public SqlConnection OpenConnection()
    {
        var conn = new SqlConnection(ConnectionString);
        conn.Open();
        return conn;
    }

    /// <summary>Disposes the fixture and drops the test database.</summary>
    public void Dispose()
    {
        var masterConnection =
            new SqlConnectionStringBuilder(ConnectionString) { InitialCatalog = "master" }.ConnectionString;

        using var conn = new SqlConnection(masterConnection);
        conn.Open();

        using var cmd = conn.CreateCommand();
        cmd.CommandText = $@"
IF DB_ID(N'{DatabaseName}') IS NOT NULL
BEGIN
    ALTER DATABASE [{DatabaseName}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DROP DATABASE [{DatabaseName}];
END";
        cmd.ExecuteNonQuery();
    }
}

[CollectionDefinition(nameof(SchemaComplianceCollection))]
public sealed class SchemaComplianceCollection : ICollectionFixture<SchemaComplianceFixture>
{
}
