#!/usr/bin/env python3
"""
Regression tests for browser-focused keybind handling.

Why this exists:
  - When WKWebView is first responder, some shortcuts still need to work
    (pane navigation, etc).
  - Control-key combos can produce control characters (e.g. Ctrl+H => backspace),
    so matching must use keyCode fallbacks.

Requires:
  - cmux running
  - Debug socket commands enabled (`set_shortcut`, `simulate_shortcut`)
"""

import os
import sys
import time
from typing import Optional

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from cmux import cmux

def focused_pane_id(client: cmux) -> Optional[str]:
    for _idx, pane_id, _count, is_focused in client.list_panes():
        if is_focused:
            return pane_id
    return None


def wait_url_contains(client: cmux, panel_id: str, needle: str, timeout_s: float = 10.0) -> None:
    start = time.time()
    while time.time() - start < timeout_s:
        url = client._send_command(f"get_url {panel_id}").strip()
        if url and not url.startswith("ERROR") and needle in url:
            return
        time.sleep(0.1)
    raise RuntimeError(f"Timed out waiting for url to contain '{needle}': {url!r}")


def test_cmd_ctrl_h_goto_split_left_from_webview(client: cmux) -> tuple[bool, str]:
    """
    Verifies: Cmd+Ctrl+H moves pane focus left while WKWebView is first responder.
    This uses the app shortcut override path so the test is hermetic.
    """
    ws_id = client.new_workspace()
    client.select_workspace(ws_id)
    time.sleep(0.5)

    # Override focus-left shortcut to Cmd+Ctrl+H for this test.
    client.set_shortcut("focus_left", "cmd+ctrl+h")

    try:
        # Create a browser pane to the right, loading a real page.
        browser_id = client.new_pane(direction="right", panel_type="browser", url="https://example.com")
        wait_url_contains(client, browser_id, "example.com", timeout_s=15.0)

        panes = client.list_panes()
        if len(panes) != 2:
            return False, f"Expected 2 panes, got {len(panes)}: {panes}"

        browser_pane_id = focused_pane_id(client)
        terminal_pane_id = next((pid for _i, pid, _n, _f in panes if pid != browser_pane_id), None)
        if not browser_pane_id or not terminal_pane_id:
            return False, f"Could not identify terminal/browser pane IDs: {panes}"

        # Force WKWebView first responder (socket-driven; avoids flaky clicking).
        client.focus_webview(browser_id)
        client.wait_for_webview_focus(browser_id, timeout_s=3.0)

        pre = focused_pane_id(client)
        if pre != browser_pane_id:
            return False, f"Expected browser pane focused before keypress, got {pre}"

        # Send Cmd+Ctrl+H via socket event injection.
        client.simulate_shortcut("cmd+ctrl+h")
        time.sleep(0.4)

        post = focused_pane_id(client)
        if post != terminal_pane_id:
            return False, f"Expected focus to move left to {terminal_pane_id}, got {post}"

        return True, "Cmd+Ctrl+H moved focus left while webview focused"
    finally:
        # Restore defaults for subsequent tests.
        try:
            client.set_shortcut("focus_left", "clear")
        except Exception:
            pass

def test_cmd_opt_left_arrow_goto_split_left_from_webview(client: cmux) -> tuple[bool, str]:
    """
    Baseline: default pane navigation (Cmd+Option+Left Arrow) moves pane focus
    left while WKWebView is first responder.
    """
    ws_id = client.new_workspace()
    client.select_workspace(ws_id)
    time.sleep(0.5)

    # Ensure we use the default arrow shortcut.
    client.set_shortcut("focus_left", "clear")

    browser_id = client.new_pane(direction="right", panel_type="browser", url="https://example.com")
    wait_url_contains(client, browser_id, "example.com", timeout_s=15.0)

    panes = client.list_panes()
    if len(panes) != 2:
        return False, f"Expected 2 panes, got {len(panes)}: {panes}"

    browser_pane_id = focused_pane_id(client)
    terminal_pane_id = next((pid for _i, pid, _n, _f in panes if pid != browser_pane_id), None)
    if not browser_pane_id or not terminal_pane_id:
        return False, f"Could not identify terminal/browser pane IDs: {panes}"

    client.focus_webview(browser_id)
    client.wait_for_webview_focus(browser_id, timeout_s=3.0)

    pre = focused_pane_id(client)
    if pre != browser_pane_id:
        return False, f"Expected browser pane focused before keypress, got {pre}"

    client.simulate_shortcut("cmd+opt+left")
    time.sleep(0.4)

    post = focused_pane_id(client)
    if post != terminal_pane_id:
        return False, f"Expected focus to move left to {terminal_pane_id}, got {post}"
    return True, "Cmd+Option+Left moved focus left while webview focused"


def main() -> int:
    print("cmux Browser Custom Keybind Tests")
    print("=" * 50)
    client = cmux()
    client.connect()

    tests = [
        ("Cmd+Opt+Left goto_split:left from webview focus", test_cmd_opt_left_arrow_goto_split_left_from_webview),
        ("Cmd+Ctrl+H goto_split:left from webview focus", test_cmd_ctrl_h_goto_split_left_from_webview),
    ]

    failed = 0
    for name, fn in tests:
        try:
            ok, msg = fn(client)
        except Exception as e:
            ok, msg = False, str(e)
        status = "PASS" if ok else "FAIL"
        print(f"{status}: {name} - {msg}")
        if not ok:
            failed += 1

    if failed == 0:
        print("\nAll tests passed.")
        return 0
    print(f"\n{failed} test(s) failed.")
    return 1


if __name__ == "__main__":
    raise SystemExit(main())
