"""Redaction property test (SPEC §7.4) — the AG-18 machine-check.

Plant canary values in temp local-file surfaces + fake API fixtures, run EVERY P1
verb in BOTH output modes, and assert the canaries appear in NO stdout / stderr /
log output. A secret value reaching any output stream fails this test.
"""

from __future__ import annotations

import io
import logging
from contextlib import redirect_stderr, redirect_stdout

import pytest

from mgf.secrets import cli
from mgf.secrets.context import Context
from mgf.secrets.forge import DeployKey
from mgf.secrets.hosts import HostStat
from mgf.secrets.registry import load
from tests._fakes import FakeForge, FakeHost, FakeWoodpecker, write_pipeline

# Canary strings that MUST never surface anywhere. Distinct, searchable literals.
CANARIES = [
    "CANARY_JWT_HEADER_zzz",
    "CANARY_DEVPI_PASSWORD_3f9a",
    "CANARY_DOCFORM_PAT_7b21",
    "CANARY_SSHKEY_material_44de",
]

REGISTRY = """\
[devpi_password]
family = "mgf"
kind = "password"
purpose = "devpi upload password"
consumers = ["publish"]
recovery = "reset"
state = "active"
policy = { allowed_repos = "*", blast_radius = "org-wide" }
rotation = { class = "password", staged = true }
verify = { probe = "devpi-login" }
surfaces = [
  { type = "woodpecker-org-secret", events = ["tag"] },
  { type = "local-file", repo = "mgf", path = "tokens/devpi_password.txt", mode = "0600" },
]

[woodpecker_token_local]
family = "mgf"
kind = "jwt-minted"
purpose = "local woodpecker token"
consumers = ["fallback"]
recovery = "mint"
state = "active"
policy = { allowed_repos = "*", blast_radius = "admin" }
rotation = { class = "jwt", staged = false }
verify = { probe = "woodpecker-user" }
surfaces = [ { type = "local-file", repo = "mgf", path = "tokens/wp.txt", mode = "0600" } ]

[codberge_pat]
family = "mgf"
kind = "api-token"
purpose = "forge PAT doc-form"
consumers = ["forge"]
recovery = "re-mint"
state = "active"
policy = { allowed_repos = "*", blast_radius = "forge" }
rotation = { class = "token", staged = false }
verify = { probe = "forge-auth" }
surfaces = [ { type = "local-file", repo = "mgf", path = "tokens/codberge", mode = "0600" } ]

[codeberg_push_key]
family = "mgf"
kind = "ssh-keypair"
purpose = "push key"
consumers = ["git push"]
recovery = "re-add"
state = "active"
policy = { allowed_repos = "*", blast_radius = "push" }
rotation = { class = "static-key", staged = true }
verify = { probe = "forge-key-fingerprint" }
surfaces = [
  { type = "local-file", repo = "mgf", path = "ssh_key/codeberg", mode = "0600" },
  { type = "host-file", host = "195.15.241.48", path = "/root/.ssh/id", mode = "0600", owner = "root" },
]
"""


def _plant_canaries(tmp_path):
    base = tmp_path / "mgf" / "my_stuff"
    (base / "tokens").mkdir(parents=True)
    (base / "ssh_key").mkdir(parents=True)
    # A real-looking JWT whose payload segment embeds a canary.
    (base / "tokens" / "wp.txt").write_text(f"eyJ{CANARIES[0]}.eyJleHAiOjB9.sig", encoding="utf-8")
    (base / "tokens" / "devpi_password.txt").write_text(CANARIES[1], encoding="utf-8")
    (base / "tokens" / "codberge").write_text(
        f"forge PATs\ntoken={CANARIES[2]}\nsecond line\n", encoding="utf-8"
    )
    (base / "ssh_key" / "codeberg").write_text(
        f"-----BEGIN KEY-----\n{CANARIES[3]}\n-----END KEY-----\n", encoding="utf-8"
    )
    # keep hygiene quiet-ish
    (tmp_path / "mgf" / ".gitignore").write_text("my_stuff/\n", encoding="utf-8")


def _fakes(tmp_path):
    write_pipeline(
        tmp_path,
        "mgf-website",
        """\
when:
  - event: tag
steps:
  - name: publish
    environment:
      P:
        from_secret: devpi_password
    commands: [echo x]
""",
    )
    wp = FakeWoodpecker(
        org_secrets={"devpi_password": {"tag"}, "steward_x": {"push"}},
        repos=[(1, "mgf-website")],
        repo_secrets={1: {"leftover_secret": {"push"}}},
    )
    # A deploy-key fingerprint is PUBLIC metadata (shown in forge UIs, declared in
    # the registry) — never a canary. The private key material lives only in the
    # local file planted above.
    forge = FakeForge(
        {
            "mgf-website": [
                DeployKey(
                    title="steward@woodpecker-prod", fingerprint="SHA256:publicfp", read_only=True
                ),
            ]
        }
    )
    hosts = FakeHost(
        {("195.15.241.48", "/root/.ssh/id"): HostStat("present", mode="644", owner="ubuntu")}
    )
    return Context(fed_root=tmp_path, woodpecker=wp, forge=forge, hosts=hosts)


@pytest.mark.parametrize(
    "argv",
    [
        ["list"],
        ["list", "--json"],
        ["show", "devpi_password"],
        ["show", "devpi_password", "--json"],
        ["show", "woodpecker_token_local", "--json"],
        ["doctor"],
        ["doctor", "--json"],
        [
            "doctor",
            "--surface",
            "woodpecker",
            "--surface",
            "forge",
            "--surface",
            "local",
            "--surface",
            "hosts",
        ],
        [
            "doctor",
            "--surface",
            "woodpecker",
            "--surface",
            "forge",
            "--surface",
            "local",
            "--surface",
            "hosts",
            "--json",
        ],
        ["probe", "woodpecker_token_local"],
        ["probe", "devpi_password", "--json"],
        ["probe", "codberge_pat"],
        ["probe", "codeberg_push_key", "--json"],
    ],
)
def test_no_canary_reaches_any_output(tmp_path, argv, caplog) -> None:
    _plant_canaries(tmp_path)
    p = tmp_path / "SECRETS.toml"
    p.write_text(REGISTRY, encoding="utf-8")
    reg = load([p])
    ctx = _fakes(tmp_path)

    out, err = io.StringIO(), io.StringIO()
    with caplog.at_level(logging.DEBUG), redirect_stdout(out), redirect_stderr(err):
        cli.main(argv, registry=reg, context=ctx)

    blob = out.getvalue() + err.getvalue() + "\n".join(r.getMessage() for r in caplog.records)
    for canary in CANARIES:
        assert canary not in blob, f"canary {canary!r} leaked into {argv} output"
