using System.Text.RegularExpressions;

namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;

public sealed class LegacyGraphClickParityWebTests
{
    private static readonly string RepositoryRoot = FindRepositoryRoot();
    private static readonly string App = File.ReadAllText(Path.Combine(
        RepositoryRoot,
        "src",
        "MBN_STOCK_WEBVIEW.LegacyParityApp",
        "Web",
        "app.js"));
    private static readonly string PackageInputHarness = File.ReadAllText(Path.Combine(
        RepositoryRoot,
        "scripts",
        "Test-LegacyPackageInput.mjs"));

    [Fact]
    public void Uc3_targets_select_on_single_click_and_fill_slots_only_on_double_click()
    {
        var doubleStart = App.IndexOf(
            "categoryTree.addEventListener(\"dblclick\"",
            StringComparison.Ordinal);
        var clickStart = App.IndexOf(
            "categoryTree.addEventListener(\"click\"",
            doubleStart + 1,
            StringComparison.Ordinal);
        var changeStart = App.IndexOf(
            "categoryTree.addEventListener(\"change\"",
            clickStart + 1,
            StringComparison.Ordinal);
        Assert.True(doubleStart >= 0 && clickStart > doubleStart && changeStart > clickStart);
        var doubleClick = App[doubleStart..clickStart];
        var singleClick = App[clickStart..changeStart];

        foreach (var intent in new[]
                 {
                     "choose-comparison-domestic",
                     "choose-comparison-world",
                     "choose-comparison-fixed"
                 })
        {
            Assert.Contains($"\"{intent}\"", doubleClick, StringComparison.Ordinal);
            Assert.DoesNotContain($"\"{intent}\"", singleClick, StringComparison.Ordinal);
        }

        foreach (var intent in new[]
                 {
                     "select-comparison-domestic",
                     "select-comparison-world",
                     "select-comparison-fixed"
                 })
        {
            Assert.Contains($"\"{intent}\"", singleClick, StringComparison.Ordinal);
            Assert.DoesNotContain($"\"{intent}\"", doubleClick, StringComparison.Ordinal);
        }

        Assert.Contains("comparisonTargetClickTimer", singleClick, StringComparison.Ordinal);
        Assert.Contains("beginComparisonTargetPendingSelection", singleClick,
            StringComparison.Ordinal);
        Assert.Contains("deferLegacySingleClick(function () {", singleClick,
            StringComparison.Ordinal);
        Assert.Contains("clearComparisonTargetPendingSelection(true)", singleClick,
            StringComparison.Ordinal);
    }

    [Fact]
    public void Vi_result_single_click_selects_and_double_click_adds_without_duplicate_intent()
    {
        var start = App.IndexOf("function renderManualLists", StringComparison.Ordinal);
        var end = App.IndexOf("function openNamedPlaylist", start, StringComparison.Ordinal);
        Assert.True(start >= 0 && end > start);
        var manual = App[start..end];

        Assert.Matches(
            new Regex(
                "addEventListener\\(\"click\"[\\s\\S]*?beginManualViResultPendingSelection[\\s\\S]*?deferLegacySingleClick[\\s\\S]*?send\\(\"select-manual-vi-result\"",
                RegexOptions.CultureInvariant),
            manual);
        Assert.Matches(
            new Regex(
                "addEventListener\\(\"dblclick\"[\\s\\S]*?clearDelayedClick\\(manualViResultClickTimer\\)[\\s\\S]*?send\\(\"add-manual-vi-result\"",
                RegexOptions.CultureInvariant),
            manual);
    }

    [Fact]
    public void GraphE_stock_candidate_single_click_focuses_and_double_click_selects_once()
    {
        var doubleStart = App.IndexOf(
            "manualWorkspace.addEventListener(\"dblclick\"",
            StringComparison.Ordinal);
        var clickStart = App.IndexOf(
            "manualWorkspace.addEventListener(\"click\"",
            doubleStart + 1,
            StringComparison.Ordinal);
        var keyStart = App.IndexOf(
            "manualWorkspace.addEventListener(\"keydown\"",
            clickStart + 1,
            StringComparison.Ordinal);
        Assert.True(doubleStart >= 0 && clickStart > doubleStart && keyStart > clickStart);
        var doubleClick = App[doubleStart..clickStart];
        var singleClick = App[clickStart..keyStart];

        Assert.Contains("button[data-manual-stock-result-id]", doubleClick,
            StringComparison.Ordinal);
        Assert.Contains("selectManualFinancialStock(stock)", doubleClick,
            StringComparison.Ordinal);
        Assert.DoesNotContain("focusManualFinancialStock(stock)", doubleClick,
            StringComparison.Ordinal);
        Assert.Contains("focusManualFinancialStock(stock)", singleClick,
            StringComparison.Ordinal);
        Assert.DoesNotContain("queueManualFinancialStockSelection", App,
            StringComparison.Ordinal);

        var helperStart = App.IndexOf(
            "function focusManualFinancialStock",
            StringComparison.Ordinal);
        var helperEnd = App.IndexOf(
            "function captureManualDraftForChangedModel",
            helperStart,
            StringComparison.Ordinal);
        Assert.True(helperStart >= 0 && helperEnd > helperStart);
        var helper = App[helperStart..helperEnd];
        Assert.DoesNotContain("deferLegacySingleClick", helper, StringComparison.Ordinal);
        Assert.Contains("stock.focus({ preventScroll: true })", helper,
            StringComparison.Ordinal);
        Assert.Single(
            Regex.Matches(helper, "send\\(\"select-manual-financial-stock\"")
                .Cast<Match>());

        var keyDown = App[keyStart..];
        Assert.Contains("selectManualFinancialStock(stock)", keyDown,
            StringComparison.Ordinal);
        Assert.Contains("event.preventDefault();", keyDown, StringComparison.Ordinal);
    }

    [Fact]
    public void Packaged_input_harness_double_clicks_GraphE_candidate_and_proves_one_intent()
    {
        Assert.Contains("beforeCandidateMessageSequence", PackageInputHarness,
            StringComparison.Ordinal);
        Assert.Contains("await pointerDoubleClick(", PackageInputHarness,
            StringComparison.Ordinal);
        Assert.Contains("select verified stock by slow Windows double-click", PackageInputHarness,
            StringComparison.Ordinal);
        Assert.Contains("message.sequence > beforeCandidateMessageSequence", PackageInputHarness,
            StringComparison.Ordinal);
        Assert.Contains("candidateMessages.length !== 1", PackageInputHarness,
            StringComparison.Ordinal);
        Assert.Contains("candidateMessages[0].type !== \"select-manual-financial-stock\"",
            PackageInputHarness,
            StringComparison.Ordinal);
        Assert.Contains("await sleep(350);", PackageInputHarness, StringComparison.Ordinal);
        Assert.Contains("SHOULD_CLEAR_ON_STOCK_CHANGE", PackageInputHarness,
            StringComparison.Ordinal);
        Assert.Contains("focusedCandidateId", PackageInputHarness, StringComparison.Ordinal);
    }

    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.");
    }
}
