from __future__ import annotations

import json


def test_doctor_cli_outputs_json(capsys) -> None:
    from pyimgano.doctor_cli import main as doctor_main

    rc = doctor_main(["--json"])
    assert rc == 0

    payload = json.loads(capsys.readouterr().out)
    assert payload.get("tool") == "pyimgano-doctor"
    assert isinstance(payload.get("pyimgano_version"), str)

    python = payload.get("python")
    assert isinstance(python, dict)
    assert isinstance(python.get("version"), str)

    platform = payload.get("platform")
    assert isinstance(platform, dict)
    assert isinstance(platform.get("system"), str)

    optional_modules = payload.get("optional_modules")
    assert isinstance(optional_modules, list)
    assert optional_modules, "expected at least one optional module check"
    for item in optional_modules:
        assert isinstance(item, dict)
        assert isinstance(item.get("module"), str)
        assert isinstance(item.get("available"), bool)

    baselines = payload.get("baselines")
    assert isinstance(baselines, dict)
    assert "industrial-v4" in set(baselines.get("suites", []))
    assert "industrial-feature-small" in set(baselines.get("sweeps", []))


def test_doctor_cli_outputs_text(capsys) -> None:
    from pyimgano.doctor_cli import main as doctor_main

    rc = doctor_main([])
    assert rc == 0

    out = capsys.readouterr().out
    assert "pyimgano-doctor" in out.lower()
    assert "pyimgano" in out.lower()


def test_doctor_cli_suite_check_outputs_json(capsys) -> None:
    from pyimgano.doctor_cli import main as doctor_main

    rc = doctor_main(["--json", "--suite", "industrial-v4"])
    assert rc == 0

    payload = json.loads(capsys.readouterr().out)
    suite_checks = payload.get("suite_checks")
    assert isinstance(suite_checks, dict)

    v4 = suite_checks.get("industrial-v4")
    assert isinstance(v4, dict)
    assert v4.get("suite") == "industrial-v4"

    baselines = v4.get("baselines")
    assert isinstance(baselines, list)
    assert baselines, "expected at least one baseline entry"

    b0 = baselines[0]
    assert isinstance(b0, dict)
    assert isinstance(b0.get("name"), str)
    assert isinstance(b0.get("optional"), bool)
    assert isinstance(b0.get("requires_extras"), list)
    assert isinstance(b0.get("missing_extras"), list)
    assert isinstance(b0.get("runnable"), bool)


def test_doctor_cli_require_extras_missing_exits_nonzero(capsys) -> None:
    from pyimgano.doctor_cli import main as doctor_main

    rc = doctor_main(["--json", "--require-extras", "definitely_missing_extra"])
    assert rc == 1

    payload = json.loads(capsys.readouterr().out)
    req = payload.get("require_extras")
    assert isinstance(req, dict)
    assert req.get("ok") is False
    assert "definitely_missing_extra" in set(req.get("missing", []))


def test_doctor_cli_require_extras_import_error_exits_nonzero(tmp_path, capsys) -> None:
    """If a module exists but fails to import, --require-extras should fail.

    This is important for CI/deploy gates: `find_spec()` is not enough when native
    wheels are present but broken (missing shared libs, ABI mismatch, etc.).
    """

    from pathlib import Path

    from pyimgano.doctor_cli import main as doctor_main

    broken_root = tmp_path / "pyimgano_broken_extra_root"
    pkg_dir = broken_root / "pyimgano__broken_extra__"
    pkg_dir.mkdir(parents=True, exist_ok=True)
    (pkg_dir / "__init__.py").write_text("raise RuntimeError('broken import')\n", encoding="utf-8")

    import sys

    sys.path.insert(0, str(broken_root))
    try:
        rc = doctor_main(["--json", "--require-extras", "pyimgano__broken_extra__"])
        assert rc == 1

        payload = json.loads(capsys.readouterr().out)
        req = payload.get("require_extras")
        assert isinstance(req, dict)
        assert req.get("ok") is False
        assert "pyimgano__broken_extra__" in set(req.get("missing", []))
    finally:
        # Avoid polluting other tests (order-independent).
        sys.path = [p for p in sys.path if str(p) != str(broken_root)]
