from __future__ import annotations

import json
import sys
from pathlib import Path

import pytest

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

import cld
import command_router


def write_rules(base_dir: Path) -> None:
    tray_dir = base_dir / ".local/state/overdeck/systray/runtime"
    tray_dir.mkdir(parents=True, exist_ok=True)
    (tray_dir / "claude_routing_rules.json").write_text(
        json.dumps(
            {
                "projects": {"zync.is": "avi"},
                "default": "rafa",
                "fallback_chain": ["roy"],
                "fallback_trigger": "broken_or_quota_exhausted",
                "quota_exhausted_threshold_pct": 100,
            }
        ),
        encoding="utf-8",
    )


@pytest.fixture
def base_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
    monkeypatch.setattr(command_router.Path, "home", lambda: tmp_path)
    monkeypatch.setattr(command_router.remote_dispatch, "in_container", lambda: True)
    write_rules(tmp_path)
    for slug in ("avi", "rafa", "roy"):
        (tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts" / slug / "CLAUDE_HOME").mkdir(
            parents=True
        )
    (tmp_path / ".local/state/overdeck/systray/runtime" / "claude_health_cache.json").write_text("{}", encoding="utf-8")
    return tmp_path


def test_main_execs_claude_with_project_account_home(
    base_dir: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    exec_call: dict[str, object] = {}
    monkeypatch.setattr(cld, "detect_project_name", lambda cwd=None: "zync.is")
    monkeypatch.setattr(command_router.ClaudeAdapter, "verify_env_support", lambda self, home: True)

    def fake_execvpe(file: str, args: list[str], env: dict[str, str]) -> None:
        exec_call["file"] = file
        exec_call["args"] = args
        exec_call["env"] = env
        raise SystemExit(0)

    monkeypatch.setattr(command_router.os, "execvpe", fake_execvpe)

    with pytest.raises(SystemExit):
        cld.main(["cld", "chat"])

    assert exec_call["file"] == "claude"
    assert exec_call["args"] == ["claude", "chat"]
    assert exec_call["env"]["CLAUDE_CONFIG_DIR"] == str(
        base_dir / ".local/state/overdeck/systray/runtime" / "claude-accounts" / "avi" / "CLAUDE_HOME"
    )


def test_main_prefers_systray_selected_default_over_project_route(
    base_dir: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    (base_dir / ".local/state/overdeck/systray/runtime" / "claude_default_slug").write_text(
        "rafa\n", encoding="utf-8"
    )
    exec_call: dict[str, object] = {}
    monkeypatch.setattr(cld, "detect_project_name", lambda cwd=None: "zync.is")
    monkeypatch.setattr(command_router.ClaudeAdapter, "verify_env_support", lambda self, home: True)

    def fake_execvpe(file: str, args: list[str], env: dict[str, str]) -> None:
        exec_call["env"] = env
        raise SystemExit(0)

    monkeypatch.setattr(command_router.os, "execvpe", fake_execvpe)

    with pytest.raises(SystemExit):
        cld.main(["cld"])

    assert exec_call["env"]["CLAUDE_CONFIG_DIR"] == str(
        base_dir / ".local/state/overdeck/systray/runtime" / "claude-accounts" / "rafa" / "CLAUDE_HOME"
    )


def test_main_execs_explicit_claude_account_override(
    base_dir: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    (base_dir / ".local/state/overdeck/systray/runtime" / "claude-accounts" / "roy" / "CLAUDE_HOME").mkdir(
        parents=True, exist_ok=True
    )
    exec_call: dict[str, object] = {}

    def fail_detect_project_name(cwd: Path | None = None) -> str:
        raise AssertionError("routing must not run when --account is given")

    monkeypatch.setattr(cld, "detect_project_name", fail_detect_project_name)
    monkeypatch.setattr(command_router.ClaudeAdapter, "verify_env_support", lambda self, home: True)

    def fake_execvpe(file: str, args: list[str], env: dict[str, str]) -> None:
        exec_call["args"] = args
        exec_call["env"] = env
        raise SystemExit(0)

    monkeypatch.setattr(command_router.os, "execvpe", fake_execvpe)

    with pytest.raises(SystemExit):
        cld.main(["cld", "--account", "roy", "--print"])

    assert exec_call["args"] == ["claude", "--print"]
    assert exec_call["env"]["CLAUDE_CONFIG_DIR"] == str(
        base_dir / ".local/state/overdeck/systray/runtime" / "claude-accounts" / "roy" / "CLAUDE_HOME"
    )


def test_main_rejects_unknown_claude_account_override(
    base_dir: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    exec_called = False

    def fake_execvpe(file: str, args: list[str], env: dict[str, str]) -> None:
        nonlocal exec_called
        exec_called = True

    monkeypatch.setattr(command_router.os, "execvpe", fake_execvpe)

    exit_code = cld.main(["cld", "--account=ghost", "chat"])

    assert exit_code == 1
    assert exec_called is False
