"""CLI contract — verbs, ``--json``, and the exit-code contract (SPEC §4, §9.1)."""

from __future__ import annotations

import json

import pytest

from mgf.secrets import cli
from mgf.secrets.context import Context
from mgf.secrets.registry import load
from tests._fakes import FakeWoodpecker

REGISTRY = """\
[alpha_secret]
family = "mgf"
kind = "api-token"
purpose = "alpha"
consumers = ["x"]
recovery = "re-mint"
state = "active"
policy = { allowed_repos = "*", blast_radius = "low" }
rotation = { class = "token", staged = true, last = "2026-07-01" }
verify = { probe = "auth" }
surfaces = [ { type = "woodpecker-org-secret", events = ["push"] } ]

[beta_key]
family = "sooth"
kind = "ssh-keypair"
purpose = "beta"
consumers = ["y"]
recovery = "re-add"
state = "held"
policy = { allowed_repos = "*", blast_radius = "low" }
rotation = { class = "static-key", staged = true }
verify = { probe = "fp" }
surfaces = [ { type = "local-file", repo = "sooth-standard", path = "k", mode = "0600" } ]
"""


@pytest.fixture
def reg(tmp_path):
    p = tmp_path / "SECRETS.toml"
    p.write_text(REGISTRY, encoding="utf-8")
    return load([p])


def _run(argv, reg, ctx=None, capsys=None):
    code = cli.main(argv, registry=reg, context=ctx)
    out = capsys.readouterr() if capsys else None
    return code, out


def test_list_human(reg, capsys) -> None:
    code, out = _run(["list"], reg, capsys=capsys)
    assert code == 0
    assert "alpha_secret" in out.out and "beta_key" in out.out


def test_list_json_is_metadata(reg, capsys) -> None:
    code, out = _run(["list", "--json"], reg, capsys=capsys)
    assert code == 0
    data = json.loads(out.out)
    assert {e["id"] for e in data} == {"alpha_secret", "beta_key"}
    assert all("value" not in json.dumps(e) for e in data)


def test_list_filters(reg, capsys) -> None:
    _code, out = _run(["list", "--family", "sooth", "--json"], reg, capsys=capsys)
    data = json.loads(out.out)
    assert [e["id"] for e in data] == ["beta_key"]
    _code, out = _run(["list", "--state", "active", "--json"], reg, capsys=capsys)
    assert [e["id"] for e in json.loads(out.out)] == ["alpha_secret"]


def test_show_json(reg, capsys) -> None:
    code, out = _run(["show", "alpha_secret", "--json"], reg, capsys=capsys)
    assert code == 0
    data = json.loads(out.out)
    assert data["kind"] == "api-token"
    assert data["surfaces"][0]["type"] == "woodpecker-org-secret"


def test_show_unknown_id_exits_2(reg, capsys) -> None:
    code, out = _run(["show", "nope"], reg, capsys=capsys)
    assert code == 2
    assert "unknown id" in out.err


def test_probe_unknown_id_exits_2(reg, capsys) -> None:
    code, _out = _run(["probe", "nope"], reg, capsys=capsys)
    assert code == 2


def test_doctor_clean_exit_0(reg, tmp_path, capsys) -> None:
    ctx = Context(
        fed_root=tmp_path,
        woodpecker=FakeWoodpecker(org_secrets={"alpha_secret": {"push"}}, repos=[]),
    )
    code, out = _run(["doctor", "--surface", "woodpecker"], reg, ctx=ctx, capsys=capsys)
    assert code == 0
    assert "clean" in out.out


def test_doctor_findings_exit_1(reg, tmp_path, capsys) -> None:
    ctx = Context(
        fed_root=tmp_path,
        woodpecker=FakeWoodpecker(org_secrets={"alpha_secret": {"tag"}}, repos=[]),
    )
    code, out = _run(["doctor", "--surface", "woodpecker", "--json"], reg, ctx=ctx, capsys=capsys)
    assert code == 1
    data = json.loads(out.out)
    assert data["clean"] is False
    assert data["findings"]


def test_load_error_exits_2(tmp_path, capsys) -> None:
    bad = tmp_path / "SECRETS.toml"
    bad.write_text('[x]\nkind = "api-token"\n', encoding="utf-8")  # missing fields
    # Point default resolution at a root with no files by passing explicit bad registry.
    from mgf.secrets.registry import RegistryError

    with pytest.raises(RegistryError):
        load([bad])


def test_version_flag(capsys) -> None:
    with pytest.raises(SystemExit) as exc:
        cli.main(["--version"])
    assert exc.value.code == 0
    assert "mgf-secrets" in capsys.readouterr().out
