"""Tests for the Janus Labs doctor command."""

from __future__ import annotations

import urllib.request

import httpx

from cli import doctor


class Args:
    pass


def _mock_completed_process(returncode: int = 0, stdout: str = "git version 2.45.0"):
    class CompletedProcess:
        def __init__(self):
            self.returncode = returncode
            self.stdout = stdout
            self.stderr = ""

    return CompletedProcess()


def test_doctor_all_pass(monkeypatch):
    monkeypatch.setattr(
        doctor,
        "run_doctor",
        lambda: [
            doctor.DoctorCheck("Python 3.12+", "ok", "Found 3.12.0"),
            doctor.DoctorCheck("Git", "ok", "git version 2.45.0"),
        ],
    )

    exit_code = doctor.cmd_doctor(Args())

    assert exit_code == 0


def test_doctor_critical_fail(monkeypatch):
    monkeypatch.setattr(doctor.sys, "version_info", (3, 10), raising=False)
    monkeypatch.setattr(doctor.metadata, "version", lambda name: "1.0.0")
    monkeypatch.setattr(doctor.shutil, "which", lambda name: f"/fake/{name}")
    monkeypatch.setattr(doctor.subprocess, "run", lambda *args, **kwargs: _mock_completed_process())

    exit_code = doctor.cmd_doctor(Args())

    assert exit_code == 1


def test_doctor_warn_only(monkeypatch):
    def fake_version(name: str) -> str:
        if name == "questionary":
            raise doctor.metadata.PackageNotFoundError(name)
        return "1.0.0"

    monkeypatch.setattr(doctor.sys, "version_info", (3, 12, 1), raising=False)
    monkeypatch.setattr(doctor.metadata, "version", fake_version)
    monkeypatch.setattr(doctor.shutil, "which", lambda name: f"/fake/{name}")
    monkeypatch.setattr(doctor.subprocess, "run", lambda *args, **kwargs: _mock_completed_process())

    exit_code = doctor.cmd_doctor(Args())

    assert exit_code == 0


def test_doctor_output_format(monkeypatch, capsys):
    monkeypatch.setattr(
        doctor,
        "run_doctor",
        lambda: [
            doctor.DoctorCheck("Python 3.12+", "ok", "Found 3.12.0"),
            doctor.DoctorCheck("Optional package: questionary", "warn", "Missing; needed for interactive menu"),
        ],
    )

    exit_code = doctor.cmd_doctor(Args())

    assert exit_code == 0
    captured = capsys.readouterr()
    assert "Janus Labs Doctor" in captured.out
    assert "Result:" in captured.out
    assert "\x1b[" not in captured.out


def test_doctor_no_network(monkeypatch):
    network_calls: list[str] = []

    def forbid_httpx(*args, **kwargs):
        network_calls.append("httpx")
        raise AssertionError("doctor command must not use httpx")

    def forbid_urlopen(*args, **kwargs):
        network_calls.append("urllib")
        raise AssertionError("doctor command must not use urllib")

    monkeypatch.setattr(doctor.sys, "version_info", (3, 12, 1), raising=False)
    monkeypatch.setattr(doctor.metadata, "version", lambda name: "1.0.0")
    monkeypatch.setattr(doctor.shutil, "which", lambda name: f"/fake/{name}")
    monkeypatch.setattr(doctor.subprocess, "run", lambda *args, **kwargs: _mock_completed_process())
    monkeypatch.setenv("OPENAI_API_KEY", "test-openai")
    monkeypatch.setenv("CI_UPLOAD_TOKEN", "test-upload")
    monkeypatch.setattr(httpx, "get", forbid_httpx)
    monkeypatch.setattr(urllib.request, "urlopen", forbid_urlopen)

    exit_code = doctor.cmd_doctor(Args())

    assert exit_code == 0
    assert network_calls == []


def test_check_agent_cli_missing(monkeypatch):
    monkeypatch.setattr(doctor.shutil, "which", lambda name: None)

    check = doctor.check_agent_cli("gemini")

    assert check.status == "warn"
    assert check.detail == "Missing from PATH"


def test_run_doctor_labels_ci_upload_token_as_ci_only(monkeypatch):
    monkeypatch.setattr(doctor.sys, "version_info", (3, 12, 1), raising=False)
    monkeypatch.setattr(doctor.metadata, "version", lambda name: "1.0.0")
    monkeypatch.setattr(doctor.shutil, "which", lambda name: f"/fake/{name}")
    monkeypatch.setattr(doctor.subprocess, "run", lambda *args, **kwargs: _mock_completed_process())
    monkeypatch.delenv("CI_UPLOAD_TOKEN", raising=False)

    checks = doctor.run_doctor()
    ci_check = next(check for check in checks if check.name == "Env: CI_UPLOAD_TOKEN")

    assert ci_check.status == "warn"
    assert ci_check.detail == "Missing; needed for baseline uploads (CI only)"
