namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;

public sealed class LegacyProgramNamedPlaylistPersistenceContractTests
{
    private static readonly string Playout = File.ReadAllText(Path.Combine(
        FindRepositoryRoot(),
        "src",
        "MBN_STOCK_WEBVIEW.LegacyParityApp",
        "MainWindow.Playout.cs"));

    private static readonly string Window = File.ReadAllText(Path.Combine(
        FindRepositoryRoot(),
        "src",
        "MBN_STOCK_WEBVIEW.LegacyParityApp",
        "MainWindow.xaml.cs"));

    private static readonly string Web = File.ReadAllText(Path.Combine(
        FindRepositoryRoot(),
        "src",
        "MBN_STOCK_WEBVIEW.LegacyParityApp",
        "Web",
        "app.js"));

    [Fact]
    public void ProgramAllowsNamedPlaylistWritesWithoutOpeningDbLoadReplacement()
    {
        var admission = Slice(
            Playout,
            "private bool CanAcceptOperatorMutation(",
            "private static bool RequiresIdlePlaylistMutation");
        var safeWrites = Slice(
            admission,
            "var isSafeNamedPlaylistPersistenceMutation",
            "var refreshAllowsMutation");

        Assert.Contains("LegacyCreateNamedPlaylistIntent", safeWrites,
            StringComparison.Ordinal);
        Assert.Contains("LegacySaveCurrentNamedPlaylistIntent", safeWrites,
            StringComparison.Ordinal);
        Assert.Contains("LegacySaveCurrentNamedPlaylistToIntent", safeWrites,
            StringComparison.Ordinal);
        Assert.Contains("LegacyDeleteSelectedNamedPlaylistIntent", safeWrites,
            StringComparison.Ordinal);
        Assert.DoesNotContain("LegacyRefreshNamedPlaylistsIntent", safeWrites,
            StringComparison.Ordinal);
        Assert.DoesNotContain("LegacyLoadSelectedNamedPlaylistIntent", safeWrites,
            StringComparison.Ordinal);
        Assert.DoesNotContain("LegacyLoadNamedPlaylistByIdIntent", safeWrites,
            StringComparison.Ordinal);
        Assert.Contains("isSafeNamedPlaylistPersistenceMutation ||", admission,
            StringComparison.Ordinal);

        var idleOnly = Slice(
            Playout,
            "private static bool RequiresIdlePlaylistMutation",
            "private static bool IsPlaylistMutationIdle");
        Assert.Contains("LegacyLoadSelectedNamedPlaylistIntent", idleOnly,
            StringComparison.Ordinal);
        Assert.Contains("LegacyLoadNamedPlaylistByIdIntent", idleOnly,
            StringComparison.Ordinal);
        Assert.DoesNotContain("LegacyCreateNamedPlaylistIntent", idleOnly,
            StringComparison.Ordinal);
        Assert.DoesNotContain("LegacySaveCurrentNamedPlaylistIntent", idleOnly,
            StringComparison.Ordinal);
        Assert.DoesNotContain("LegacySaveCurrentNamedPlaylistToIntent", idleOnly,
            StringComparison.Ordinal);
        Assert.DoesNotContain("LegacyDeleteSelectedNamedPlaylistIntent", idleOnly,
            StringComparison.Ordinal);
    }

    [Fact]
    public void NamedPlaylistModalRequestsUseOnePendingSlotBehindRefresh()
    {
        Assert.Contains(
            "private readonly SemaphoreSlim _orderedNamedPlaylistIntentGate = new(1, 1);",
            Window,
            StringComparison.Ordinal);

        var process = Slice(
            Window,
            "private async Task ProcessIntentAsync",
            "private LegacyOperatorSnapshot SelectCutWithoutAppend");
        var queued = Slice(
            process,
            "else if (IsNamedPlaylistModalIntent(intent))",
            "// Keep the zero-timeout admission used by database and edit intents;");
        Assert.Contains("_orderedNamedPlaylistIntentGate.WaitAsync(", queued,
            StringComparison.Ordinal);
        Assert.Contains("0,", queued, StringComparison.Ordinal);
        Assert.Contains("await _intentGate.WaitAsync", queued,
            StringComparison.Ordinal);
        Assert.Contains("_orderedNamedPlaylistIntentGate.Release();", process,
            StringComparison.Ordinal);

        var classifier = Slice(
            Window,
            "private static bool IsNamedPlaylistModalIntent",
            "private LegacyOperatorSnapshot ReportIntentFailure");
        foreach (var intent in new[]
                 {
                     "LegacyRefreshNamedPlaylistsIntent",
                     "LegacySelectNamedPlaylistIntent",
                     "LegacyLoadSelectedNamedPlaylistIntent",
                     "LegacyLoadNamedPlaylistByIdIntent",
                     "LegacyCreateNamedPlaylistIntent",
                     "LegacySaveCurrentNamedPlaylistIntent",
                     "LegacySaveCurrentNamedPlaylistToIntent",
                     "LegacyDeleteSelectedNamedPlaylistIntent",
                     "LegacyDismissDialogIntent"
                 })
        {
            Assert.Contains(intent, classifier, StringComparison.Ordinal);
        }

        Assert.Contains("else if (intent is LegacyDismissDialogIntent)", process,
            StringComparison.Ordinal);
        Assert.Contains("PostState(_controller.Current);", process,
            StringComparison.Ordinal);
    }

    [Fact]
    public void OneButtonResultDialogCannotLoseItsClickToBackgroundBusyState()
    {
        Assert.Contains(
            "dialogOk.disabled = legacyDialogIsConfirmation && state.isBusy === true;",
            Web,
            StringComparison.Ordinal);
    }

    [Fact]
    public void NamedPlaylistConfirmationReenablesBothActionsWhenItOpens()
    {
        var open = Slice(
            Web,
            "function openNamedPlaylistConfirmation",
            "function restoreNamedPlaylistAfterConfirmation");

        Assert.Contains("if (!options || isNamedPlaylistActionLocked()) return false;",
            open,
            StringComparison.Ordinal);
        Assert.Contains("namedPlaylistConfirmationYes.disabled = false;",
            open,
            StringComparison.Ordinal);
        Assert.Contains("namedPlaylistConfirmationNo.disabled = false;",
            open,
            StringComparison.Ordinal);
    }

    [Fact]
    public void OpenNamedPlaylistConfirmationDoesNotLoseClickToProgramRefresh()
    {
        var render = Slice(
            Web,
            "function renderNamedPlaylist",
            "function clearOperatorCatalogDragVisuals");
        var confirmationLock = Slice(
            render,
            "namedPlaylistConfirmationYes.disabled =",
            "if (deferredSelectionAction)");

        Assert.Contains("pendingNamedPlaylistCommand !== null", confirmationLock,
            StringComparison.Ordinal);
        Assert.Contains("namedPlaylistState.isWriteInProgress === true", confirmationLock,
            StringComparison.Ordinal);
        Assert.DoesNotContain("operatorMutationLocked", confirmationLock,
            StringComparison.Ordinal);
        Assert.DoesNotContain("uiBusy", confirmationLock,
            StringComparison.Ordinal);
    }

    private static string Slice(string source, string startMarker, string endMarker)
    {
        var start = source.IndexOf(startMarker, StringComparison.Ordinal);
        var end = source.IndexOf(endMarker, start + startMarker.Length,
            StringComparison.Ordinal);
        Assert.True(start >= 0, $"Missing source marker: {startMarker}");
        Assert.True(end > start, $"Missing source marker: {endMarker}");
        return source[start..end];
    }

    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("Could not locate the repository root.");
    }
}
