from __future__ import annotations

import importlib.util
import sys
from pathlib import Path


def _load_cli_module():
    spec = importlib.util.spec_from_file_location("soigia_cli", Path("soigia/cli.py"))
    module = importlib.util.module_from_spec(spec)
    assert spec.loader is not None
    sys.modules[spec.name] = module
    spec.loader.exec_module(module)
    return module


def test_resolve_layout_target_accepts_preset_and_numeric():
    cli = _load_cli_module()

    pane_count, preset = cli._resolve_layout_target("4")
    assert pane_count == 4
    assert preset is None

    pane_count, preset = cli._resolve_layout_target("dev")
    assert pane_count == 3
    assert preset is not None
    assert preset.name == "dev"

    pane_count, preset = cli._resolve_layout_target("api")
    assert pane_count == 3
    assert preset is not None
    assert preset.name == "api"


def test_completion_script_mentions_powershell_completer():
    cli = _load_cli_module()

    script = cli._completion_script("powershell")

    assert "Register-ArgumentCompleter" in script
    assert "soigia" in script
    assert "suggest" in script
    assert "completion" in script
    assert "install-completion" in script
    assert "menu" in script


def test_completion_script_supports_bash_and_zsh():
    cli = _load_cli_module()

    bash_script = cli._completion_script("bash")
    zsh_script = cli._completion_script("zsh")

    assert "compgen" in bash_script
    assert "complete -F" in bash_script
    assert "#compdef" in zsh_script
    assert "_arguments" in zsh_script


def test_detect_shell_prefers_environment(monkeypatch):
    cli = _load_cli_module()
    monkeypatch.setenv("SHELL", "/usr/bin/zsh")
    assert cli._detect_shell() == "zsh"
    monkeypatch.setenv("SHELL", "/bin/bash")
    assert cli._detect_shell() == "bash"


def test_build_wt_command_uses_titles_and_segments(monkeypatch):
    cli = _load_cli_module()
    monkeypatch.setattr(cli, "_find_wt_executable", lambda: "wt.exe")

    pane_specs = cli._build_pane_specs(4, pane_titles=("dev", "tests", "logs", "notes"))
    command = cli._build_wt_command(pane_specs, r"C:\work")

    assert isinstance(command, list)
    assert command[0] == "wt.exe"
    assert "new-tab" in command
    assert "split-pane" in command
    assert "--title" in command
    assert "dev" in command
    assert "notes" in command
    assert ";" in command


def test_build_pane_specs_merges_custom_commands():
    cli = _load_cli_module()

    specs = cli._build_pane_specs(
        3,
        preset=cli.PRESETS["api"],
        pane_titles=("api", "tests", "docs"),
        pane_commands=[("powershell.exe", "-NoExit", "-Command", "Write-Host 'custom'")],
    )

    assert specs[0].title == "api"
    assert specs[0].command_template[0] == "powershell.exe"
    assert specs[1].title == "tests"
    assert specs[1].command_template
    assert specs[2].title == "docs"


def test_parse_pane_command_splits_command_line():
    cli = _load_cli_module()

    command = cli._parse_pane_command("powershell.exe -NoExit -Command \"Write-Host hi\"")

    assert command[0] == "powershell.exe"
    assert "-NoExit" in command
    assert "Write-Host hi" in command[-1]


def test_menu_routes_to_known_preset(monkeypatch):
    cli = _load_cli_module()
    responses = iter(["api", "launch"])
    monkeypatch.setattr(cli, "_menu_prompt", lambda title, options: next(responses))
    monkeypatch.setattr(cli, "_run_command", lambda command: None)

    result = cli._run_menu(object(), type("Args", (), {"cwd": None, "completion_shell": None, "profile": None})())

    assert result == 0


def test_preset_submenu_preview_and_dry_run(monkeypatch):
    cli = _load_cli_module()
    preset = cli.PRESETS["web"]
    args = type("Args", (), {"cwd": None})()

    monkeypatch.setattr(cli, "_menu_prompt", lambda title, options: "preview")
    monkeypatch.setattr(cli, "_preview_layout", lambda *args, **kwargs: None)
    assert cli._preset_submenu(object(), args, preset) == 0

    monkeypatch.setattr(cli, "_menu_prompt", lambda title, options: "dry-run")
    monkeypatch.setattr(cli, "_show_command_preview", lambda command: None)
    monkeypatch.setattr(cli, "_build_wt_command", lambda pane_specs, cwd: ["wt.exe", "new-tab"])
    assert cli._preset_submenu(object(), args, preset) == 0


def test_recent_layout_storage_roundtrip(monkeypatch):
    cli = _load_cli_module()
    recent_file = Path.cwd() / ".test_artifacts" / "recent.json"
    recent_file.parent.mkdir(parents=True, exist_ok=True)
    if recent_file.exists():
        recent_file.unlink()
    monkeypatch.setenv(cli.RECENT_ENV_PATH, str(recent_file))

    cli._remember_layout("api")
    cli._remember_layout("web")
    cli._remember_layout("api")

    assert cli._load_recent_layouts() == ["api", "web"]
    assert recent_file.exists()
    recent_file.unlink(missing_ok=True)


def test_menu_routes_to_recent(monkeypatch):
    cli = _load_cli_module()
    recent_file = Path.cwd() / ".test_artifacts" / "recent.json"
    recent_file.parent.mkdir(parents=True, exist_ok=True)
    recent_file.write_text('["api"]', encoding="utf-8")
    monkeypatch.setenv(cli.RECENT_ENV_PATH, str(recent_file))
    responses = iter(["recent", "1", "launch"])
    monkeypatch.setattr(cli, "_menu_prompt", lambda title, options: next(responses))
    monkeypatch.setattr(cli, "_run_command", lambda command: None)

    result = cli._run_menu(object(), type("Args", (), {"cwd": None, "completion_shell": None, "profile": None})())

    assert result == 0
    recent_file.unlink(missing_ok=True)


def test_install_completion_writes_marker_block():
    cli = _load_cli_module()
    profile = Path.cwd() / ".test_artifacts" / "cli-profile.ps1"
    profile.parent.mkdir(parents=True, exist_ok=True)
    if profile.exists():
        profile.unlink()

    installed_path = cli._install_completion("powershell", str(profile))

    text = installed_path.read_text(encoding="utf-8")
    assert cli.INSTALL_MARKER_START in text
    assert cli.INSTALL_MARKER_END in text
    assert "Register-ArgumentCompleter" in text
    installed_path.unlink(missing_ok=True)
