using Microsoft.Data.SqlClient;

namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.TestSupport.Probes;

/// <summary>
///     Verifies the Galaxy Repository SQL side: SQL Server reachable, <c>ZB</c> database
///     present, and at least one deployed object exists (so live tests have something to read).
///     Reuses the Windows-auth connection string the repo code defaults to.
/// </summary>
public static class SqlProbe
{
    public const string DefaultConnectionString =
        "Server=localhost;Database=ZB;Integrated Security=True;TrustServerCertificate=True;Encrypt=False;Connect Timeout=3;";

    public static async Task<PrerequisiteCheck> CheckZbDatabaseAsync(
        string? connectionString = null, CancellationToken ct = default)
    {
        connectionString ??= DefaultConnectionString;
        try
        {
            using var conn = new SqlConnection(connectionString);
            await conn.OpenAsync(ct);

            // DB_ID returns null when the database doesn't exist on the connected server — distinct
            // failure mode from "server unreachable", deserves a distinct message.
            using var cmd = conn.CreateCommand();
            cmd.CommandText = "SELECT DB_ID('ZB')";
            var dbIdObj = await cmd.ExecuteScalarAsync(ct);
            if (dbIdObj is null || dbIdObj is DBNull)
            {
                return new PrerequisiteCheck("sql:ZB", PrerequisiteCategory.GalaxyRepository,
                    PrerequisiteStatus.Fail,
                    "SQL Server reachable but database ZB does not exist. " +
                    "Create the Galaxy from the IDE or restore a .cab backup.");
            }

            return new PrerequisiteCheck("sql:ZB", PrerequisiteCategory.GalaxyRepository,
                PrerequisiteStatus.Pass, "Connected; ZB database exists.");
        }
        catch (SqlException ex)
        {
            return new PrerequisiteCheck("sql:ZB", PrerequisiteCategory.GalaxyRepository,
                PrerequisiteStatus.Fail,
                $"SQL Server unreachable: {ex.Message}. Ensure MSSQLSERVER service is running (sc.exe start MSSQLSERVER) and TCP 1433 is open.");
        }
        catch (Exception ex)
        {
            return new PrerequisiteCheck("sql:ZB", PrerequisiteCategory.GalaxyRepository,
                PrerequisiteStatus.Fail,
                $"Unexpected probe error: {ex.GetType().Name}: {ex.Message}");
        }
    }

    /// <summary>
    ///     Returns the count of deployed Galaxy objects (<c>deployed_version &gt; 0</c>). Zero
    ///     isn't a hard failure — lets someone boot a fresh Galaxy and still get meaningful
    ///     test-suite output — but it IS a warning because any live-read smoke will have
    ///     nothing to read.
    /// </summary>
    public static async Task<PrerequisiteCheck> CheckDeployedObjectCountAsync(
        string? connectionString = null, CancellationToken ct = default)
    {
        connectionString ??= DefaultConnectionString;
        try
        {
            using var conn = new SqlConnection(connectionString);
            await conn.OpenAsync(ct);
            using var cmd = conn.CreateCommand();
            cmd.CommandText = "SELECT COUNT(*) FROM gobject WHERE deployed_version > 0";
            var countObj = await cmd.ExecuteScalarAsync(ct);
            var count = countObj is int i ? i : 0;

            return count > 0
                ? new PrerequisiteCheck("sql:ZB.deployedObjects", PrerequisiteCategory.GalaxyRepository,
                    PrerequisiteStatus.Pass, $"{count} objects deployed — live reads have data to return.")
                : new PrerequisiteCheck("sql:ZB.deployedObjects", PrerequisiteCategory.GalaxyRepository,
                    PrerequisiteStatus.Warn,
                    "ZB contains no deployed objects. Discovery smoke tests will return empty hierarchies; " +
                    "deploy at least a Platform + AppEngine from the IDE to exercise the read path.");
        }
        catch (Exception ex)
        {
            return new PrerequisiteCheck("sql:ZB.deployedObjects", PrerequisiteCategory.GalaxyRepository,
                PrerequisiteStatus.Warn,
                $"Couldn't count deployed objects: {ex.GetType().Name}: {ex.Message}");
        }
    }
}
