namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;

public sealed class LegacyDatabaseHealthMonitorNativeContractTests
{
    private static readonly string RepositoryRoot = FindRepositoryRoot();
    private static readonly string AppRoot = Path.Combine(
        RepositoryRoot,
        "src",
        "MBN_STOCK_WEBVIEW.LegacyParityApp");
    private static readonly string Window = File.ReadAllText(
        Path.Combine(AppRoot, "MainWindow.xaml.cs"));
    private static readonly string Monitor = File.ReadAllText(
        Path.Combine(AppRoot, "MainWindow.DatabaseHealth.cs"));
    private static readonly string Playout = File.ReadAllText(
        Path.Combine(AppRoot, "MainWindow.Playout.cs"));

    [Fact]
    public void LegacyTenSecondMonitorStartsAndStopsWithTheActiveWindow()
    {
        Assert.Contains(
            "TimeSpan.FromSeconds(10)",
            Monitor,
            StringComparison.Ordinal);
        Assert.Contains(
            "await Task.Delay(DatabaseHealthPollingInterval, cancellationToken)",
            Monitor,
            StringComparison.Ordinal);
        Assert.Contains(
            "StartDatabaseHealthMonitor();",
            Window,
            StringComparison.Ordinal);
        Assert.Contains(
            "_lifetimeCancellation.Cancel();\n        CancelActiveDatabaseHealthCheck();",
            Normalize(Window),
            StringComparison.Ordinal);
    }

    [Fact]
    public void MonitorUsesBothConfiguredProvidersAndLogsOnlyClosedTransitions()
    {
        Assert.Contains(
            ".HealthService\n                .CheckAllAsync(healthCancellation.Token)",
            Normalize(Monitor),
            StringComparison.Ordinal);
        Assert.Contains(
            "foreach (var status in statuses)",
            Monitor,
            StringComparison.Ordinal);
        Assert.Contains(
            "ObserveDatabaseHealthState(status.Source, status.State);",
            Monitor,
            StringComparison.Ordinal);
        Assert.Contains(
            "_databaseHealthTransitions.TryObserveDatabaseState(",
            Monitor,
            StringComparison.Ordinal);
        Assert.Contains(
            "_databaseHealthLogWriter.TryWrite(record)",
            Monitor,
            StringComparison.Ordinal);
        Assert.DoesNotContain("status.UserMessage", Monitor, StringComparison.Ordinal);
        Assert.DoesNotContain("exception.Message", Monitor, StringComparison.Ordinal);
    }

    [Fact]
    public void OperatorAndRefreshWorkCancelAndSerializeAgainstHealthProbes()
    {
        var dispatch = Slice(
            Window,
            "private async Task ProcessIntentAsync(",
            "private static bool IsNamedPlaylistModalIntent(");
        var databaseWait = RequiredIndex(
            dispatch,
            "await AcquirePriorityDatabaseActivityAsync(_lifetimeCancellation.Token)");
        var handle = RequiredIndex(dispatch, "await HandleIntentAsync(");
        Assert.True(databaseWait < handle);
        Assert.Contains("_databaseActivityGate.Release();", dispatch,
            StringComparison.Ordinal);

        var refresh = Slice(
            Playout,
            "private async Task RunRefreshLoopAsync(",
            "private bool TrySetRefreshFault(");
        databaseWait = RequiredIndex(
            refresh,
            "await AcquirePriorityDatabaseActivityAsync(token)");
        var refreshCall = RequiredIndex(refresh, "workflow.RefreshOnAirAsync");
        Assert.True(databaseWait < refreshCall);
        Assert.Contains("_databaseActivityGate.Release();", refresh,
            StringComparison.Ordinal);
    }

    [Fact]
    public void OperatorPriorityClosesTheHealthProbeCancellationPublishRace()
    {
        var acquire = Slice(
            Monitor,
            "private async Task AcquirePriorityDatabaseActivityAsync(",
            "private void CancelActiveDatabaseHealthCheck()");
        var waiterIncrement = RequiredIndex(
            acquire,
            "Interlocked.Increment(ref _databaseActivityPriorityWaiterCount);");
        var cancel = RequiredIndex(acquire, "CancelActiveDatabaseHealthCheck();");
        var gateWait = RequiredIndex(
            acquire,
            "await _databaseActivityGate.WaitAsync(cancellationToken)");
        var waiterDecrement = RequiredIndex(
            acquire,
            "Interlocked.Decrement(ref _databaseActivityPriorityWaiterCount);");
        Assert.True(waiterIncrement < cancel);
        Assert.True(cancel < gateWait);
        Assert.True(gateWait < waiterDecrement);

        var probe = Slice(
            Monitor,
            "private async Task CheckAndLogDatabaseHealthAsync(",
            "private async Task AcquirePriorityDatabaseActivityAsync(");
        var preAcquirePriorityCheck = RequiredIndex(
            probe,
            "Volatile.Read(ref _databaseActivityPriorityWaiterCount) != 0");
        var healthCancellationPublish = RequiredIndex(
            probe,
            "Interlocked.Exchange(\n                ref _databaseHealthCheckCancellation,\n                healthCancellation);");
        var postPublishPriorityCheck = RequiredIndex(
            probe,
            "Volatile.Read(ref _databaseActivityPriorityWaiterCount) != 0",
            healthCancellationPublish);
        var providerProbe = RequiredIndex(probe, ".CheckAllAsync(healthCancellation.Token)");
        Assert.True(preAcquirePriorityCheck < healthCancellationPublish);
        Assert.True(healthCancellationPublish < postPublishPriorityCheck);
        Assert.True(postPublishPriorityCheck < providerProbe);
    }

    private static string Normalize(string value) =>
        value.Replace("\r\n", "\n", StringComparison.Ordinal);

    private static string Slice(string value, string start, string end)
    {
        var startIndex = RequiredIndex(value, start);
        var endIndex = RequiredIndex(value, end, startIndex + start.Length);
        return value[startIndex..endIndex];
    }

    private static int RequiredIndex(string value, string needle, int startIndex = 0)
    {
        var index = value.IndexOf(needle, startIndex, StringComparison.Ordinal);
        Assert.True(index >= 0, $"Required marker was not found: {needle}");
        return index;
    }

    private static string FindRepositoryRoot()
    {
        var directory = new DirectoryInfo(AppContext.BaseDirectory);
        while (directory is not null)
        {
            if (File.Exists(Path.Combine(directory.FullName, "MBN_STOCK_WEBVIEW.sln")))
            {
                return directory.FullName;
            }

            directory = directory.Parent;
        }

        throw new DirectoryNotFoundException("Repository root was not found.");
    }
}
