"""
Tests for issue #1045 — bfcache layout broken on tab restore.

When the browser restores a page from bfcache (event.persisted === true),
the async boot IIFE does not re-run. The existing pageshow handler (added for
#822) only cleared the session search field and re-rendered the session list.
This left the rail, topbar, workspace panel, and resize handles in the stale
bfcache DOM state, producing a broken layout.

Fix: extend the pageshow handler to also call syncTopbar, syncWorkspacePanelState,
_initResizePanels, and startGatewaySSE — all guarded so missing helpers degrade.
"""

from pathlib import Path

ROOT = Path(__file__).parent.parent


def _boot_js() -> str:
    return (ROOT / "static" / "boot.js").read_text(encoding="utf-8")


def _pageshow_handler(src: str) -> str:
    marker = "window.addEventListener('pageshow'"
    ps_idx = src.find(marker)
    assert ps_idx != -1, "pageshow listener not found in boot.js"
    brace = src.find("=> {", ps_idx)
    assert brace != -1, "pageshow listener body not found"
    brace = src.find("{", brace)
    depth = 1
    i = brace + 1
    while i < len(src) and depth:
        if src[i] == "{":
            depth += 1
        elif src[i] == "}":
            depth -= 1
        i += 1
    assert depth == 0, "pageshow listener body did not close"
    return src[brace + 1 : i - 1]


class TestBfcacheLayoutRestore:
    def test_pageshow_calls_sync_topbar(self):
        """pageshow handler must call syncTopbar() on bfcache restore."""
        src = _boot_js()
        handler_body = _pageshow_handler(src)
        assert "syncTopbar" in handler_body, (
            "pageshow handler must call syncTopbar() to restore topbar state after bfcache"
        )

    def test_pageshow_calls_sync_workspace_panel_state(self):
        """pageshow handler must call syncWorkspacePanelState()."""
        src = _boot_js()
        handler_body = _pageshow_handler(src)
        assert "syncWorkspacePanelState" in handler_body, (
            "pageshow handler must call syncWorkspacePanelState() on bfcache restore"
        )


    def test_pageshow_calls_start_gateway_sse(self):
        """pageshow handler must call startGatewaySSE() to reconnect the dead SSE connection."""
        src = _boot_js()
        handler_body = _pageshow_handler(src)
        assert "startGatewaySSE" in handler_body, (
            "pageshow handler must restart gateway SSE (bfcache-persisted connections are dead)"
        )

    def test_pageshow_still_clears_session_search(self):
        """pageshow handler must still clear #sessionSearch (original #822 fix preserved)."""
        src = _boot_js()
        handler_body = _pageshow_handler(src)
        assert "sessionSearch" in handler_body, (
            "pageshow handler must still clear #sessionSearch (regression: #822 fix must be preserved)"
        )

    def test_pageshow_still_calls_render_session_list_from_cache(self):
        """pageshow handler must still call renderSessionListFromCache()."""
        src = _boot_js()
        handler_body = _pageshow_handler(src)
        assert "renderSessionListFromCache" in handler_body, (
            "pageshow handler must still call renderSessionListFromCache() (regression: #822 fix)"
        )

    def test_pageshow_does_not_call_init_resize_panels(self):
        """pageshow handler must NOT call _initResizePanels() — bfcache
        preserves event listeners so re-attaching them stacks duplicates."""
        src = _boot_js()
        handler_body = _pageshow_handler(src)
        assert "_initResizePanels" not in handler_body, (
            "pageshow handler must not call _initResizePanels() — it stacks "
            "duplicate mousedown listeners on every bfcache restore"
        )

    def test_new_calls_are_guarded_with_typeof(self):
        """New calls in the pageshow handler must be typeof-guarded for safe degradation."""
        src = _boot_js()
        handler_body = _pageshow_handler(src)
        # Each of the new calls must be guarded
        for fn in ("syncTopbar", "syncWorkspacePanelState", "startGatewaySSE",
                   "closeModelDropdown", "closeReasoningDropdown", "closeWsDropdown", "closeProfileDropdown"):
            assert f"typeof {fn} === 'function'" in handler_body, (
                f"{fn}() call in pageshow handler must be guarded with typeof === 'function'"
            )

    def test_pageshow_closes_all_dropdowns(self):
        """pageshow handler must close all known dropdowns to reset frozen bfcache popover state."""
        src = _boot_js()
        handler_body = _pageshow_handler(src)
        for fn in ("closeModelDropdown", "closeReasoningDropdown", "closeWsDropdown", "closeProfileDropdown"):
            assert fn in handler_body, (
                f"pageshow handler must call {fn}() to dismiss any dropdown left open by bfcache"
            )

    def test_dropdowns_closed_before_layout_sync(self):
        """Dropdown closes must come before layout sync calls (clean state first)."""
        src = _boot_js()
        handler_body = _pageshow_handler(src)
        close_idx = handler_body.find("closeModelDropdown")
        sync_idx = handler_body.find("syncTopbar")
        assert close_idx != -1 and sync_idx != -1, "Both close and sync calls must be present"
        assert close_idx < sync_idx, (
            "Dropdown close calls must appear before layout sync calls in the pageshow handler"
        )

