using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;

namespace ZB.MOM.WW.ScadaBridge.SiteEventLogging.Tests;

/// <summary>
/// Regression tests for SiteEventLogging-006: the schema must index the columns the
/// query service filters on so common queries do not full-scan a 1 GB database.
/// </summary>
public class SchemaIndexTests : IDisposable
{
    private readonly SiteEventLogger _logger;
    private readonly SqliteConnection _verifyConnection;
    private readonly string _dbPath;
    private readonly TestLocalDb _localDb;

    public SchemaIndexTests()
    {
        _dbPath = Path.Combine(Path.GetTempPath(), $"test_index_{Guid.NewGuid()}.db");
        var options = Options.Create(new SiteEventLogOptions { DatabasePath = _dbPath });
        _localDb = TestLocalDb.Create(_dbPath);
        _logger = new SiteEventLogger(options, NullLogger<SiteEventLogger>.Instance, _localDb.Db);

        _verifyConnection = new SqliteConnection($"Data Source={_dbPath}");
        _verifyConnection.Open();
    }

    public void Dispose()
    {
        _verifyConnection.Dispose();
        _logger.Dispose();
        _localDb.Dispose();
        TestLocalDb.DeleteFiles(_dbPath);
    }

    [Fact]
    public void Schema_HasIndexOnSeverity()
    {
        using var cmd = _verifyConnection.CreateCommand();
        cmd.CommandText =
            "SELECT name FROM sqlite_master WHERE type = 'index' AND tbl_name = 'site_events'";
        var indexes = new List<string>();
        using var reader = cmd.ExecuteReader();
        while (reader.Read()) indexes.Add(reader.GetString(0));

        Assert.Contains("idx_events_severity", indexes);
    }

    [Fact]
    public async Task SeverityFilteredQuery_UsesIndex_NotFullScan()
    {
        await _logger.LogEventAsync("script", "Error", null, "S", "boom");
        await _logger.LogEventAsync("script", "Info", null, "S", "ok");

        using var cmd = _verifyConnection.CreateCommand();
        cmd.CommandText =
            "EXPLAIN QUERY PLAN SELECT id FROM site_events WHERE severity = 'Error'";
        var plan = new System.Text.StringBuilder();
        using var reader = cmd.ExecuteReader();
        while (reader.Read())
        {
            // The detail column holds the human-readable plan step.
            plan.Append(reader.GetString(reader.GetOrdinal("detail"))).Append('\n');
        }

        var planText = plan.ToString();
        Assert.Contains("idx_events_severity", planText);
        Assert.DoesNotContain("SCAN site_events", planText);
    }
}
