namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;

public sealed class LegacyFixedSectionBatchWebTests
{
    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 MainWindow = File.ReadAllText(Path.Combine(
        RepositoryRoot,
        "src",
        "MBN_STOCK_WEBVIEW.LegacyParityApp",
        "MainWindow.xaml.cs"));
    private static readonly string Playout = File.ReadAllText(Path.Combine(
        RepositoryRoot,
        "src",
        "MBN_STOCK_WEBVIEW.LegacyParityApp",
        "MainWindow.Playout.cs"));

    [Fact]
    public void Fixed_section_progress_is_native_state_and_locks_other_catalog_actions()
    {
        var fixedCatalog = Extract("function renderFixedCatalog", "function renderIndustry");

        Assert.Contains("const batch = state.fixedSectionBatch", fixedCatalog,
            StringComparison.Ordinal);
        Assert.Contains("button.disabled = state.isBusy === true || batch != null",
            fixedCatalog,
            StringComparison.Ordinal);
        Assert.Contains("summary.setAttribute(\"aria-disabled\"", fixedCatalog,
            StringComparison.Ordinal);
        Assert.Contains("section.getAttribute(\"aria-disabled\") !== \"true\"", App,
            StringComparison.Ordinal);
        Assert.Contains("send(\"activate-fixed-section\"", App,
            StringComparison.Ordinal);
    }

    [Fact]
    public void Manual_modal_explains_atomic_staging_and_exposes_only_confirm_next_or_cancel()
    {
        var manual = Extract("function renderManualLists", "function openNamedPlaylist");

        Assert.Contains("const fixedBatch = state.fixedSectionBatch", manual,
            StringComparison.Ordinal);
        Assert.Contains("아직 편성표에 추가되지 않았습니다", manual, StringComparison.Ordinal);
        Assert.Contains("button.disabled = fixedBatch != null", manual,
            StringComparison.Ordinal);
        Assert.Contains("setTransientControlsBusy(manualListDialog, state.isBusy === true)", manual,
            StringComparison.Ordinal);
        Assert.Contains("확인 후 다음", manual, StringComparison.Ordinal);
        Assert.Contains("확인 후 섹션 추가", manual, StringComparison.Ordinal);
        Assert.Contains("send(\"confirm-manual-list\", {})", manual, StringComparison.Ordinal);
        Assert.DoesNotContain("resume-fixed-section", App, StringComparison.Ordinal);
    }

    [Fact]
    public void Native_dispatch_awaits_the_whole_fixed_section_workflow()
    {
        Assert.Contains("await _controller.ActivateFixedSection(", MainWindow,
            StringComparison.Ordinal);
        Assert.Contains("section.SectionIndex", MainWindow, StringComparison.Ordinal);
        Assert.Contains("cancellationToken", MainWindow, StringComparison.Ordinal);
    }

    [Fact]
    public void Native_fixed_page_preflight_keeps_the_catalog_busy_until_database_read_finishes()
    {
        var busyIntents = Extract(
            MainWindow,
            "if ((intent is LegacySearchStocksIntent",
            "await AcquirePriorityDatabaseActivityAsync");

        Assert.Contains("LegacyActivateFixedActionIntent", busyIntents,
            StringComparison.Ordinal);
        Assert.Contains("LegacyActivateFixedSectionIntent", busyIntents,
            StringComparison.Ordinal);
    }

    [Fact]
    public void Native_boundary_allows_only_current_manual_edits_until_batch_completion()
    {
        var allowlist = Extract(
            Playout,
            "private static bool IsFixedSectionBatchMutationIntent",
            "private void ObserveOperatorMutationQuarantine");
        Assert.Contains("_controller.Current.FixedSectionBatch is not null", MainWindow,
            StringComparison.Ordinal);
        Assert.Contains("!IsFixedSectionBatchMutationIntent(intent)", MainWindow,
            StringComparison.Ordinal);
        Assert.Contains("LegacySetManualNetSellCellIntent", allowlist, StringComparison.Ordinal);
        Assert.Contains("LegacyConfirmManualListIntent", allowlist, StringComparison.Ordinal);
        Assert.DoesNotContain("LegacyDropSelectedCutsIntent", allowlist, StringComparison.Ordinal);
    }

    private static string Extract(string startToken, string endToken)
    {
        return Extract(App, startToken, endToken);
    }

    private static string Extract(string source, string startToken, string endToken)
    {
        var start = source.IndexOf(startToken, StringComparison.Ordinal);
        var end = source.IndexOf(endToken, start + startToken.Length, StringComparison.Ordinal);
        Assert.True(start >= 0 && end > start);
        return source[start..end];
    }

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

            current = current.Parent;
        }

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