"""CLI entry point for ai-interview-assistant."""

from __future__ import annotations

import json
import os
import subprocess
import sys
import time
from pathlib import Path

import click

from ai_interview.config import (
    CHALLENGE_TYPES,
    CLAUDE_MODELS,
    CONFIG_FILE,
    LOG_FILE,
    Config,
    load_saved_config,
    save_config,
)
from ai_interview.daemon import is_process_running, kill_existing, read_meta, read_pid


@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
    """AI Interview Assistant — ghost background tool for live code challenges."""
    if ctx.invoked_subcommand is None:
        ctx.invoke(start)


# ---------------------------------------------------------------------------
# helpers
# ---------------------------------------------------------------------------

def _menu(title: str, options: list[str], descriptions: list[str] | None = None) -> int:
    """Show an arrow-key navigable menu. Returns selected index."""
    from simple_term_menu import TerminalMenu

    if descriptions:
        entries = [f"  {opt}  — {desc}" for opt, desc in zip(options, descriptions)]
    else:
        entries = [f"  {opt}" for opt in options]

    click.echo(f"\n  {title}\n")
    menu = TerminalMenu(
        entries,
        cursor_index=0,
        menu_cursor="  ▸ ",
        menu_cursor_style=("fg_cyan", "bold"),
        menu_highlight_style=("fg_cyan", "bold"),
    )
    idx = menu.show()
    if idx is None:
        sys.exit(0)
    return idx


def _prompt_provider_key(saved: dict) -> dict:
    """Prompt for AI provider choice and key via arrow menu. Returns updated saved dict."""
    idx = _menu(
        "Choose your AI provider:",
        ["Gemini (Google)", "Claude (Anthropic)"],
        ["free, no credit card needed", "best quality, paid"],
    )

    if idx == 1:  # Claude
        click.echo("\n  Get your key at: https://console.anthropic.com/settings/keys\n")
        key = click.prompt("  Anthropic API key")
        if not key.strip():
            click.echo("  API key is required.", err=True)
            sys.exit(1)
        saved["anthropic_api_key"] = key.strip()
        saved["preferred_provider"] = "claude"
    else:  # Gemini
        click.echo("\n  Get your free key at: https://aistudio.google.com/api-keys\n")
        key = click.prompt("  Google API key")
        if not key.strip():
            click.echo("  API key is required.", err=True)
            sys.exit(1)
        saved["google_api_key"] = key.strip()
        saved["preferred_provider"] = "gemini"

    return saved


def _ensure_api_keys() -> dict:
    """Check saved config for API keys; prompt inline if missing. Returns saved config."""
    saved = load_saved_config()
    has_anthropic = saved.get("anthropic_api_key") or os.environ.get("ANTHROPIC_API_KEY")
    has_google = saved.get("google_api_key") or os.environ.get("GOOGLE_API_KEY")

    if has_anthropic or has_google:
        return saved

    click.echo("")
    click.echo("  Welcome to AI Interview Assistant!")
    click.echo("  " + "─" * 38)

    idx = _menu(
        "How do you want to set up?",
        ["Quick setup", "Full setup"],
        ["free, just a Google API key", "Anthropic + Deepgram keys, best quality + transcription"],
    )

    if idx == 1:
        # Full setup — run the setup wizard in full mode
        click.echo("")
        _run_full_setup(saved)
        return load_saved_config()

    # Quick setup — Gemini + language only
    click.echo("\n  Get your free key at: https://aistudio.google.com/api-keys\n")
    key = click.prompt("  Google API key")
    if not key.strip():
        click.echo("  API key is required.", err=True)
        sys.exit(1)
    saved["google_api_key"] = key.strip()
    saved["preferred_provider"] = "gemini"

    # Language selection
    langs = ["English", "Portuguese", "Spanish", "French", "German", "Chinese", "Japanese", "Other"]
    lang_codes = ["en", "pt", "es", "fr", "de", "zh", "ja", None]
    lang_idx = _menu("Interview language:", langs)
    if lang_codes[lang_idx] is None:
        code = click.prompt("  Language code (e.g. ko, ru, it)")
    else:
        code = lang_codes[lang_idx]
    saved["transcription_language"] = code
    # Mark as quick setup so start skips per-interview prompts
    if not saved.get("interview_language"):
        saved["interview_language"] = "General"
    saved["setup_mode"] = "quick"

    save_config(saved)

    click.echo("")
    click.echo("  Commands:")
    click.echo("    ai-interview            start the assistant")
    click.echo("    ai-interview stop       stop it")
    click.echo("    ai-interview provider   switch AI provider")
    click.echo("    ai-interview setup      reconfigure")
    click.echo("    ai-interview version    update")
    click.echo("")

    return saved


# ---------------------------------------------------------------------------
# setup wizard
# ---------------------------------------------------------------------------

def _run_full_setup(saved: dict) -> None:
    """Run the full 4-step setup wizard."""
    click.echo("  [1/4] API Keys\n")
    click.echo("  Claude (paid, best): https://console.anthropic.com/settings/keys")
    click.echo("  Gemini (free):       https://aistudio.google.com/api-keys")
    click.echo("  Deepgram:            https://console.deepgram.com/")
    click.echo("")

    current_anthropic = saved.get("anthropic_api_key", "")
    anthropic_prompt = "  Anthropic API key (Enter to skip)"
    if current_anthropic:
        anthropic_prompt += f" [{'*' * 8 + current_anthropic[-4:]}]"
    anthropic_key = click.prompt(anthropic_prompt, default=current_anthropic or "", show_default=False)

    current_google = saved.get("google_api_key", "")
    google_prompt = "  Google Gemini API key (Enter to skip)"
    if current_google:
        google_prompt += f" [{'*' * 8 + current_google[-4:]}]"
    google_key = click.prompt(google_prompt, default=current_google or "", show_default=False)

    if not anthropic_key and not google_key:
        click.echo("  At least one AI provider key is required.", err=True)
        sys.exit(1)

    current_deepgram = saved.get("deepgram_api_key", "")
    deepgram_prompt = "  Deepgram API key (Enter to skip)"
    if current_deepgram:
        deepgram_prompt += f" [{'*' * 8 + current_deepgram[-4:]}]"
    deepgram_key = click.prompt(deepgram_prompt, default=current_deepgram or "", show_default=False)

    click.echo("")

    # --- [2/4] Interview defaults ---
    click.echo("  [2/4] Interview Defaults\n")

    lang_default = saved.get("interview_language", "Python")
    language = click.prompt("  Programming language", default=lang_default)

    challenge_idx = _menu(
        "[2/4] Challenge type:",
        CHALLENGE_TYPES,
    )
    challenge = CHALLENGE_TYPES[challenge_idx]

    transcription_default = saved.get("transcription_language", "en")
    transcription_lang = click.prompt("  Transcription language (en/pt/es/fr/de…)", default=transcription_default)

    # Codebase path with tab-completion
    try:
        import readline
        import glob as _glob

        def _path_completer(text, state):
            expanded = os.path.expanduser(text)
            matches = _glob.glob(expanded + "*")
            matches = [m + "/" if os.path.isdir(m) else m for m in matches]
            return matches[state] if state < len(matches) else None

        _old_completer = readline.get_completer()
        _old_delims = readline.get_completer_delims()
        readline.set_completer(_path_completer)
        readline.set_completer_delims(" \t\n")
        if "libedit" in readline.__doc__:
            readline.parse_and_bind("bind ^I rl_complete")
        else:
            readline.parse_and_bind("tab: complete")
    except ImportError:
        _old_completer = None
        _old_delims = None

    ctx_default = saved.get("context_path", "")
    click.echo(f"  Codebase path (Enter to skip){f' [{ctx_default}]' if ctx_default else ''}: ", nl=False)
    raw = input().strip() or ctx_default

    try:
        import readline
        readline.set_completer(_old_completer)
        if _old_delims is not None:
            readline.set_completer_delims(_old_delims)
    except ImportError:
        pass

    context_path = ""
    if raw:
        p = Path(raw).expanduser().resolve()
        if p.is_dir():
            context_path = str(p)
        else:
            click.echo(f"  Warning: {raw} is not a directory — skipping.")

    click.echo("")

    # --- [3/4] AI Model ---
    model_names = list(CLAUDE_MODELS.keys())
    model_descs = ["fast, great for most challenges (recommended)", "smarter, ~2x slower", "fastest, lighter answers"]
    model_idx = _menu("[3/4] AI Model:", model_names, model_descs)
    model = model_names[model_idx]

    click.echo("")

    # --- [4/4] Network ---
    port_default = saved.get("port", 7890)
    port = click.prompt("  [4/4] Viewer port", default=port_default)

    # --- Save ---
    config_data = {
        **saved,
        "anthropic_api_key": anthropic_key,
        "google_api_key": google_key,
        "deepgram_api_key": deepgram_key,
        "interview_language": language,
        "challenge_type": challenge,
        "transcription_language": transcription_lang,
        "context_path": context_path,
        "claude_model": model,
        "port": port,
    }
    if anthropic_key:
        config_data["preferred_provider"] = "claude"
    config_data["setup_mode"] = "full"
    save_config(config_data)

    click.echo("")
    click.echo(f"  Saved to {CONFIG_FILE}")
    click.echo("  Ready! Run:  ai-interview")
    click.echo("")


@cli.command()
@click.option("--simple", "mode", flag_value="simple", help="Quick setup — just API key")
@click.option("--full", "mode", flag_value="full", help="Full setup — all settings")
def setup(mode):
    """Configure the assistant (API keys, model, language, etc.)."""
    saved = load_saved_config()

    click.echo("")
    click.echo("  AI Interview Assistant — Setup")
    click.echo("  " + "─" * 38)

    if mode is None:
        idx = _menu(
            "Setup mode:",
            ["Simple", "Full"],
            ["just paste an API key and go", "configure everything (keys, model, language, port)"],
        )
        mode = "simple" if idx == 0 else "full"

    if mode == "simple":
        click.echo("")
        saved = _prompt_provider_key(saved)
        save_config(saved)
        click.echo("")
        click.echo(f"  Saved to {CONFIG_FILE}")
        click.echo("  Ready! Run:  ai-interview")
        click.echo("")
        return

    click.echo("")
    _run_full_setup(saved)


# ---------------------------------------------------------------------------
# start
# ---------------------------------------------------------------------------

@cli.command()
@click.option("--api-key", envvar="ANTHROPIC_API_KEY", default=None,
              help="Anthropic API key (overrides saved config)")
@click.option("--google-key", envvar="GOOGLE_API_KEY", default=None,
              help="Google Gemini API key (overrides saved config)")
@click.option("--deepgram-key", envvar="DEEPGRAM_API_KEY", default=None,
              help="Deepgram API key (overrides saved config)")
@click.option("--port", default=None, type=int,
              help="Viewer server port (overrides saved config)")
@click.option("--language", default=None,
              help="Programming language for this session (skips prompt)")
@click.option("--transcription-lang", default=None,
              help="Transcription language code (skips prompt)")
@click.option("--challenge-type", default=None,
              help="Challenge type for this session")
@click.option("--context-path", default=None, type=click.Path(exists=True, file_okay=False, resolve_path=True),
              help="Path to repo — AI will have full codebase context")
@click.option("--model", default=None, type=click.Choice(list(CLAUDE_MODELS.keys())),
              help="Claude model override")
@click.option("--daemon", is_flag=True, hidden=True)
def start(api_key, google_key, deepgram_key, port, language, transcription_lang, challenge_type,
          context_path, model, daemon):
    """Start the assistant in the background."""
    # Build overrides dict from CLI flags
    overrides = {}
    if api_key:
        overrides["anthropic_api_key"] = api_key
    if google_key:
        overrides["google_api_key"] = google_key
    if deepgram_key:
        overrides["deepgram_api_key"] = deepgram_key
    if port:
        overrides["port"] = port
    if language:
        overrides["interview_language"] = language
    if transcription_lang:
        overrides["transcription_language"] = transcription_lang
    if challenge_type:
        overrides["challenge_type"] = challenge_type
    if context_path:
        overrides["context_path"] = context_path
    if model:
        overrides["claude_model"] = model

    if daemon:
        config = Config.from_saved(overrides)
        if config.provider == "none":
            sys.stderr.write("No API key configured. Run: ai-interview setup\n")
            sys.exit(1)
        from ai_interview.daemon import run_daemon
        run_daemon(config)
        return

    # ---- Interactive prompts (only in non-daemon mode) ----
    saved = _ensure_api_keys()

    # Skip prompts only for quick-setup users; full-setup users get per-interview prompts
    if saved.get("setup_mode") != "quick":
        if language is None:
            lang_default = saved.get("interview_language", "Python")
            language = click.prompt("  Programming language", default=lang_default)
            overrides["interview_language"] = language
            saved["interview_language"] = language

        if transcription_lang is None:
            trans_default = saved.get("transcription_language", "en")
            transcription_lang = click.prompt(
                "  Transcription language (en/pt/es/fr/de…)", default=trans_default
            )
            overrides["transcription_language"] = transcription_lang
            saved["transcription_language"] = transcription_lang

        # Persist selections for next run
        save_config(saved)

        if context_path is None:
            # Enable filesystem tab-completion for the path prompt
            try:
                import readline
                import glob as _glob

                def _path_completer(text, state):
                    expanded = os.path.expanduser(text)
                    matches = _glob.glob(expanded + "*")
                    matches = [m + "/" if os.path.isdir(m) else m for m in matches]
                    return matches[state] if state < len(matches) else None

                _old_completer = readline.get_completer()
                _old_delims = readline.get_completer_delims()
                readline.set_completer(_path_completer)
                readline.set_completer_delims(" \t\n")
                if "libedit" in readline.__doc__:
                    readline.parse_and_bind("bind ^I rl_complete")
                else:
                    readline.parse_and_bind("tab: complete")
            except ImportError:
                _old_completer = None
                _old_delims = None

            click.echo("  Codebase path (Enter to skip): ", nl=False)
            raw = input().strip()

            try:
                import readline
                readline.set_completer(_old_completer)
                if _old_delims is not None:
                    readline.set_completer_delims(_old_delims)
            except ImportError:
                pass
            if raw:
                p = Path(raw).expanduser().resolve()
                if not p.is_dir():
                    click.echo(f"  Warning: {raw} is not a directory — skipping codebase context.")
                else:
                    context_path = str(p)
                    overrides["context_path"] = context_path

    click.echo("")

    # Validate config before spawning
    config = Config.from_saved(overrides)
    if config.provider == "none":
        click.echo("No API key configured.", err=True)
        click.echo("Run:  ai-interview setup", err=True)
        sys.exit(1)

    if not config.deepgram_api_key:
        click.echo("  Note: No Deepgram key — will use local Whisper (slower). Run setup to add it.")

    # Kill any running instance
    pid = read_pid()
    if pid and is_process_running(pid):
        click.echo("Stopping existing instance…")
        kill_existing()
        time.sleep(0.5)

    if config.context_path:
        click.echo(f"  Reading codebase: {config.context_path} …")

    # Spawn fresh subprocess that daemonizes itself
    cmd = [sys.executable, "-m", "ai_interview", "start", "--daemon"]

    # Pass all resolved values explicitly so daemon subprocess doesn't need config file
    if config.anthropic_api_key:
        cmd += ["--api-key", config.anthropic_api_key]
    if config.google_api_key:
        cmd += ["--google-key", config.google_api_key]
    if config.deepgram_api_key:
        cmd += ["--deepgram-key", config.deepgram_api_key]
    cmd += ["--port", str(config.port)]
    if config.interview_language:
        cmd += ["--language", config.interview_language]
    if config.transcription_language:
        cmd += ["--transcription-lang", config.transcription_language]
    if config.challenge_type:
        cmd += ["--challenge-type", config.challenge_type]
    if config.context_path:
        cmd += ["--context-path", config.context_path]
    if model:
        cmd += ["--model", model]

    subprocess.Popen(
        cmd,
        start_new_session=True,
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
        stdin=subprocess.DEVNULL,
    )

    for _ in range(30):
        time.sleep(0.2)
        p = read_pid()
        if p and is_process_running(p):
            transcriber_info = "Deepgram (real-time)" if config.deepgram_api_key else "Whisper (local, ~10s delay)"

            click.echo(f"  Started  (pid={p})")
            click.echo(f"  Viewer:    http://localhost:{config.port}")
            click.echo(f"  Language:  {config.interview_language or '(not set)'}")
            click.echo(f"  Transcript: {config.transcription_language}  |  {transcriber_info}")
            if config.context_path:
                click.echo(f"  Codebase:  {config.context_path}")
            model_name = config.claude_model if config.provider == "claude" else config.gemini_model
            click.echo(f"  Provider:  {config.provider.capitalize()}")
            click.echo(f"  Model:     {model_name}")
            click.echo(f"  Logs:      {LOG_FILE}")
            click.echo("")
            click.echo("  ⌨️  Quick Reference")
            click.echo("")
            click.echo("    📸  ESC + ↓              capture screenshot")
            click.echo("    🚀  Cmd Cmd              send to AI")
            click.echo("    📋  Ctrl Ctrl            copy selection + send")
            click.echo("    🎙️   ESC ESC + hold       voice recording")
            click.echo("    📜  ESC + ←/→            scroll viewer")
            click.echo("    🔄  ESC + [ / ]          prev/next response")
            click.echo("    🔤  ESC + = / -          font size")
            click.echo("    👁️   ESC ESC + release    toggle overlay")
            click.echo("")
            return

    click.echo(f"Failed to start — check logs: {LOG_FILE}", err=True)
    sys.exit(1)


# ---------------------------------------------------------------------------
# stop / status / qr / logs / ui
# ---------------------------------------------------------------------------

@cli.command()
def stop():
    """Stop the running assistant."""
    if kill_existing():
        click.echo("Stopped.")
    else:
        click.echo("Not running.")


@cli.command()
def restart():
    """Force restart using the same config as the last session."""
    meta = read_meta()
    saved = load_saved_config()

    if not meta and not saved:
        click.echo("No previous session found. Run: ai-interview start", err=True)
        sys.exit(1)

    # Force kill — don't wait gracefully
    pid = read_pid()
    if pid and is_process_running(pid):
        import signal
        try:
            os.kill(pid, signal.SIGKILL)
        except Exception:
            pass
        kill_existing()
    click.echo("  Killed previous instance")
    time.sleep(0.3)

    # Build config from saved + meta overrides
    overrides = {}
    if meta:
        if meta.get("interview_language"):
            overrides["interview_language"] = meta["interview_language"]
        if meta.get("challenge_type"):
            overrides["challenge_type"] = meta["challenge_type"]
        if meta.get("context_path"):
            overrides["context_path"] = meta["context_path"]
        if meta.get("port"):
            overrides["port"] = meta["port"]

    config = Config.from_saved(overrides)
    if config.provider == "none":
        click.echo("No API key configured. Run: ai-interview setup", err=True)
        sys.exit(1)

    # Spawn daemon with same params
    cmd = [sys.executable, "-m", "ai_interview", "start", "--daemon"]
    if config.anthropic_api_key:
        cmd += ["--api-key", config.anthropic_api_key]
    if config.google_api_key:
        cmd += ["--google-key", config.google_api_key]
    if config.deepgram_api_key:
        cmd += ["--deepgram-key", config.deepgram_api_key]
    cmd += ["--port", str(config.port)]
    if config.interview_language:
        cmd += ["--language", config.interview_language]
    if config.transcription_language:
        cmd += ["--transcription-lang", config.transcription_language]
    if config.challenge_type:
        cmd += ["--challenge-type", config.challenge_type]
    if config.context_path:
        cmd += ["--context-path", config.context_path]

    subprocess.Popen(
        cmd,
        start_new_session=True,
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
        stdin=subprocess.DEVNULL,
    )

    for _ in range(30):
        time.sleep(0.2)
        p = read_pid()
        if p and is_process_running(p):
            click.echo(f"  Restarted (pid={p})")
            click.echo(f"  Viewer: http://localhost:{config.port}")
            return

    click.echo(f"Failed to restart — check logs: {LOG_FILE}", err=True)


@cli.command()
def status():
    """Show running status."""
    pid = read_pid()
    if pid is None or not is_process_running(pid):
        click.echo("Status: not running")
        return

    meta = read_meta() or {}
    started_at = meta.get("started_at", 0)
    port = meta.get("port", 7890)
    uptime_secs = int(time.time() - started_at)
    h, rem = divmod(uptime_secs, 3600)
    m, s = divmod(rem, 60)

    from ai_interview.utils import get_local_ip
    ip = get_local_ip()

    click.echo(f"  Status:     running (pid={pid})")
    click.echo(f"  Uptime:     {h}h {m}m {s}s")
    click.echo(f"  Viewer:     http://{ip}:{port}")
    click.echo(f"  Transcript: {meta.get('transcriber', '?')}")
    click.echo(f"  Model:      {meta.get('claude_model', '?')}")
    if meta.get("interview_language"):
        click.echo(f"  Language:   {meta['interview_language']}")
    if meta.get("challenge_type"):
        click.echo(f"  Challenge:  {meta['challenge_type']}")
    if meta.get("context_path"):
        click.echo(f"  Codebase:   {meta['context_path']}")
    click.echo(f"  Log:        {LOG_FILE}")


@cli.command()
def qr():
    """Print QR code with the viewer URL for easy phone connection."""
    pid = read_pid()
    if pid is None or not is_process_running(pid):
        click.echo("Assistant is not running. Start it first.", err=True)
        sys.exit(1)

    meta = read_meta() or {}
    port = meta.get("port", 7890)

    from ai_interview.utils import get_local_ip, generate_qr
    ip = get_local_ip()
    url = f"http://{ip}:{port}"
    click.echo(f"\nViewer URL: {url}\n")
    click.echo(generate_qr(url))


@cli.command()
@click.option("-n", "--lines", default=50, show_default=True)
def logs(lines):
    """Tail the daemon log (Ctrl+C to stop)."""
    if not LOG_FILE.exists():
        click.echo("No log file found. Has the assistant been started?")
        return
    try:
        subprocess.run(["tail", f"-{lines}", "-f", str(LOG_FILE)])
    except KeyboardInterrupt:
        pass


@cli.command()
@click.argument("text")
@click.option("--no-trigger", is_flag=True, help="Inject text without sending to Claude")
def send(text, no_trigger):
    """Inject text as if it were spoken — useful for testing without audio.

    Example:
        ai-interview send "implement a binary search in Python"
    """
    import urllib.request
    import urllib.error

    pid = read_pid()
    if pid is None or not is_process_running(pid):
        click.echo("Assistant is not running. Start it first.", err=True)
        sys.exit(1)

    meta = read_meta() or {}
    port = meta.get("port", 7890)

    payload = json.dumps({"text": text, "trigger": not no_trigger}).encode()
    try:
        req = urllib.request.Request(
            f"http://localhost:{port}/inject",
            data=payload,
            headers={"Content-Type": "application/json"},
            method="POST",
        )
        with urllib.request.urlopen(req, timeout=5) as resp:
            result = json.loads(resp.read())
        if no_trigger:
            click.echo(f"  Injected: {result['text']!r} (not sent to Claude)")
        else:
            click.echo(f"  Sent: {result['text']!r}")
    except urllib.error.URLError as exc:
        click.echo(f"Failed to reach daemon: {exc}", err=True)
        sys.exit(1)


@cli.command()
@click.argument("name", required=False, default=None, type=click.Choice(["claude", "gemini"]))
def provider(name):
    """View or switch AI provider.

    \b
    Examples:
        ai-interview provider          show current provider
        ai-interview provider claude    switch to Claude
        ai-interview provider gemini    switch to Gemini
    """
    saved = load_saved_config()

    if name is None:
        # Show current provider
        config = Config.from_saved()
        if config.provider == "none":
            click.echo("  No provider configured. Run: ai-interview setup")
            return
        model = config.claude_model if config.provider == "claude" else config.gemini_model
        click.echo(f"  Provider:  {config.provider.capitalize()}")
        click.echo(f"  Model:     {model}")
        click.echo("")
        click.echo("  Switch with: ai-interview provider claude")
        click.echo("           or: ai-interview provider gemini")
        return

    # Switch provider
    if name == "claude":
        if not saved.get("anthropic_api_key"):
            click.echo("")
            click.echo("  Get your key at: https://console.anthropic.com/settings/keys")
            click.echo("")
            key = click.prompt("  Anthropic API key")
            if not key.strip():
                click.echo("  Key is required.", err=True)
                sys.exit(1)
            saved["anthropic_api_key"] = key.strip()
        saved["preferred_provider"] = "claude"
        save_config(saved)
        click.echo("  Switched to Claude")

    elif name == "gemini":
        if not saved.get("google_api_key"):
            click.echo("")
            click.echo("  Get your free key at: https://aistudio.google.com/api-keys")
            click.echo("")
            key = click.prompt("  Google API key")
            if not key.strip():
                click.echo("  Key is required.", err=True)
                sys.exit(1)
            saved["google_api_key"] = key.strip()
        saved["preferred_provider"] = "gemini"
        save_config(saved)
        click.echo("  Switched to Gemini")


@cli.command()
def hotkeys():
    """Show hotkey reference."""
    click.echo("")
    click.echo("  Hotkeys")
    click.echo("  " + "─" * 50)
    click.echo("")
    click.echo("  🤖 Ask AI")
    click.echo("")
    click.echo("    Take a screenshot and ask AI about it:")
    click.echo("      1. Press ESC + ↓  to capture screenshot")
    click.echo("      2. Press Cmd Cmd  to send to AI")
    click.echo("")
    click.echo("    Copy code from editor and ask AI:")
    click.echo("      1. Select the code")
    click.echo("      2. Press Ctrl Ctrl  to copy + send")
    click.echo("")
    click.echo("    Ask with your voice:")
    click.echo("      1. Press ESC ESC and hold")
    click.echo("      2. Speak your question")
    click.echo("      3. Release ESC")
    click.echo("")
    click.echo("  📱 Navigate")
    click.echo("")
    click.echo("    ESC + ←/→        scroll viewer up/down")
    click.echo("    ESC + [ / ]      prev/next response")
    click.echo("    ESC + = / -      font size up/down")
    click.echo("")
    click.echo("  🖥️  Overlay")
    click.echo("")
    click.echo("    ESC ESC (release quickly)   show/hide overlay")
    click.echo("")
    click.echo("  ⌨️  Quick Reference")
    click.echo("")
    click.echo("    📸  ESC + ↓              capture screenshot")
    click.echo("    🚀  Cmd Cmd              send to AI")
    click.echo("    📋  Ctrl Ctrl            copy selection + send")
    click.echo("    🎙️   ESC ESC + hold       voice recording")
    click.echo("    📜  ESC + ←/→            scroll viewer")
    click.echo("    🔄  ESC + [ / ]          prev/next response")
    click.echo("    🔤  ESC + = / -          font size")
    click.echo("    👁️   ESC ESC + release    toggle overlay")
    click.echo("")


@cli.command()
def ui():
    """Open the native overlay window on this screen."""
    pid = read_pid()
    if pid is None or not is_process_running(pid):
        click.echo("Assistant is not running. Start it first.", err=True)
        sys.exit(1)

    meta = read_meta() or {}
    port = meta.get("port", 7890)

    ui_log = Path.home() / ".ai-interview-ui.log"
    with open(ui_log, "a") as log_fh:
        subprocess.Popen(
            [sys.executable, "-m", "ai_interview.overlay", str(port)],
            stdout=log_fh,
            stderr=log_fh,
            stdin=subprocess.DEVNULL,
        )
    click.echo(f"Overlay opened (connecting to port {port})")
    click.echo(f"UI log: {ui_log}")


@cli.command()
def version():
    """Show current version and update to latest from PyPI."""
    from ai_interview import __version__

    click.echo(f"  ai-interview-assistant v{__version__}")
    click.echo("  Updating to latest version…")

    result = subprocess.run(
        ["pipx", "install", "--force", "--pip-args=--no-cache-dir", "ai-interview-assistant"],
        capture_output=True,
        text=True,
    )

    if result.returncode == 0:
        # Read new version from the freshly installed package
        ver_result = subprocess.run(
            ["python3", "-c", "from ai_interview import __version__; print(__version__)"],
            capture_output=True,
            text=True,
        )
        new_ver = ver_result.stdout.strip() if ver_result.returncode == 0 else "unknown"
        if new_ver == __version__:
            click.echo(f"  Already on latest version (v{__version__})")
        else:
            click.echo(f"  Updated: v{__version__} → v{new_ver}")
    else:
        click.echo("  Update failed. Try manually: pipx install --force ai-interview-assistant", err=True)
        if result.stderr.strip():
            click.echo(f"  {result.stderr.strip()}", err=True)
