"""Doctor determinism hardening (SPEC §4; AC §8.3).

A check that could not be PERFORMED reports ``unverifiable`` — distinct from clean
AND from a real finding (exit 1; a ``--json`` ``unverifiable`` list). ``ALL_MANAGED``
resolves to the same defined union every run on the same inputs, computed once.
"""

from __future__ import annotations

import json

from mgf.secrets.doctor import Doctor
from mgf.secrets.forge import DeployKey
from mgf.secrets.managed import resolve_all_managed_detail
from mgf.secrets.registry import load
from tests._fakes import FakeForge, FakeWoodpecker

FLEET = """\
[fleet_key]
family = "mgf"
kind = "ssh-deploy-key"
purpose = "fleet clone key"
consumers = ["clone"]
recovery = "re-add"
state = "active"
policy = { allowed_repos = "*", blast_radius = "read" }
rotation = { class = "static-key", staged = true }
verify = { probe = "forge-key-fingerprint" }
surfaces = [ { type = "forge-deploy-key", repos = "ALL_MANAGED", readonly = true, title = "ci-clone" } ]
"""


def _reg(tmp_path):
    p = tmp_path / "SECRETS.toml"
    p.write_text(FLEET, encoding="utf-8")
    return load([p])


# --------------------------------------------------------------------------- #
# Rate-limited forge → unverifiable, never silently-clean, never a false finding.
# --------------------------------------------------------------------------- #


def test_forge_429_is_unverifiable_not_clean_not_finding(tmp_path) -> None:
    reg = _reg(tmp_path)
    key = DeployKey(title="ci-clone", fingerprint="SHA256:a", read_only=True)
    wp = FakeWoodpecker(repos=[(1, "repo-a"), (2, "repo-b")])
    # repo-a covered; repo-b is rate-limited (429) — coverage there is UNVERIFIABLE.
    forge = FakeForge({"repo-a": [key], "repo-b": []}, rate_limited={"repo-b"})
    report = Doctor(reg, fed_root=tmp_path, woodpecker=wp, forge=forge).run(["forge"])
    # not clean, not a false C5 "missing" finding for repo-b — an unverifiable record.
    assert report.exit_code() == 1
    assert not any(f.check == "C5" and f.evidence.get("repo") == "repo-b" for f in report.findings)
    assert any(u.check == "C5" and "repo-b" in u.target for u in report.unverifiable)


def test_genuinely_missing_key_is_a_finding_not_unverifiable(tmp_path) -> None:
    """The distinction holds both ways: a repo we COULD read that lacks the key is a
    real C5 finding, never an unverifiable."""
    reg = _reg(tmp_path)
    key = DeployKey(title="ci-clone", fingerprint="SHA256:a", read_only=True)
    wp = FakeWoodpecker(repos=[(1, "repo-a"), (2, "repo-b")])
    forge = FakeForge({"repo-a": [key], "repo-b": []})  # repo-b readable + missing key
    report = Doctor(reg, fed_root=tmp_path, woodpecker=wp, forge=forge).run(["forge"])
    assert any(f.check == "C5" and f.evidence.get("repo") == "repo-b" for f in report.findings)
    assert not report.unverifiable


def test_unverifiable_in_json_and_distinct_from_clean(tmp_path) -> None:
    reg = _reg(tmp_path)
    wp = FakeWoodpecker(repos=[(1, "repo-a")])
    forge = FakeForge({"repo-a": []}, rate_limited={"repo-a"})
    report = Doctor(reg, fed_root=tmp_path, woodpecker=wp, forge=forge).run(["forge"])
    js = json.loads(json.dumps(report.to_json()))  # round-trips cleanly
    assert js["clean"] is False
    # both coverage checks (C5) and the unregistered-key sweep (C3) couldn't read repo-a.
    assert {u["check"] for u in js["unverifiable"]} == {"C3", "C5"}
    assert all("repo-a" in u["target"] for u in js["unverifiable"])
    assert js["findings"] == []  # couldn't-look is NOT a finding


# --------------------------------------------------------------------------- #
# Deterministic ALL_MANAGED — computed once, stable, the defined union.
# --------------------------------------------------------------------------- #


def _seed_libraries(tmp_path):
    (tmp_path / "mgf-standard").mkdir(parents=True)
    (tmp_path / "sooth-standard").mkdir(parents=True)
    (tmp_path / "mgf-standard" / "MGF_LIBRARIES.json").write_text(
        json.dumps({"libraries": [{"repo": "mgf-alembic"}, {"repo": "mgf-uitest-web"}]}),
        encoding="utf-8",
    )
    (tmp_path / "sooth-standard" / "SOOTH_LIBRARIES.json").write_text(
        json.dumps({"repos": [{"name": "soothfast"}, {"slug": "sooth-standard"}]}),
        encoding="utf-8",
    )


def test_all_managed_is_the_defined_union(tmp_path) -> None:
    _seed_libraries(tmp_path)
    res = resolve_all_managed_detail(fed_root=tmp_path, activated_repos=["hrb-app", "mgf-alembic"])
    assert res.repos == frozenset(
        {"mgf-alembic", "mgf-uitest-web", "soothfast", "sooth-standard", "hrb-app"}
    )
    # provenance is logged (count + per-source), so a cron can attribute the fleet.
    assert res.sources == {
        "MGF_LIBRARIES": 2,
        "SOOTH_LIBRARIES": 2,
        "woodpecker_activated": 2,
    }
    assert res.count == 5


def test_all_managed_stable_across_runs(tmp_path) -> None:
    _seed_libraries(tmp_path)
    a = resolve_all_managed_detail(fed_root=tmp_path, activated_repos=["hrb-app"])
    b = resolve_all_managed_detail(fed_root=tmp_path, activated_repos=["hrb-app"])
    assert a.repos == b.repos and a.sources == b.sources


def test_doctor_computes_all_managed_once_and_logs_it(tmp_path) -> None:
    _seed_libraries(tmp_path)
    (tmp_path / "SECRETS.toml").write_text(FLEET, encoding="utf-8")
    reg = load([tmp_path / "SECRETS.toml"])
    key = DeployKey(title="ci-clone", fingerprint="SHA256:a", read_only=True)
    # C3 (deploy-keys) AND C5 both iterate the managed set — it must be resolved ONCE.
    wp = FakeWoodpecker(repos=[(1, "mgf-alembic")])
    forge = FakeForge(
        {r: [key] for r in ("mgf-alembic", "mgf-uitest-web", "soothfast", "sooth-standard")}
    )
    report = Doctor(reg, fed_root=tmp_path, woodpecker=wp, forge=forge).run(["forge"])
    assert report.managed is not None and report.managed.count == 4
    # logged exactly once in skipped (count + sources), not per-check.
    logged = [s for s in report.skipped if "ALL_MANAGED resolved" in s]
    assert len(logged) == 1
