"""Sync surface coverage — the real store paths Fable runs live.

Exercises the DEFAULT value provider (secret value from the store, the sync
create path), the local surface (materialize delegation), and the forge/host note
paths. TEST keys only (AG-18). Deploy-key public-key sourcing is covered in
test_sync_contract (reuse from a repo that already carries the titled key)."""

from __future__ import annotations

from datetime import UTC, datetime
from pathlib import Path

from pyrage import x25519

from mgf.secrets import store as store_mod
from mgf.secrets.hosts import HostStat
from mgf.secrets.registry import load
from mgf.secrets.sync import Reconciler
from tests._fakes import FakeForge, FakeHost, FakeWoodpecker

REGISTRY = """\
[org_pub]
family = "mgf"
kind = "api-token"
purpose = "org secret with a stored value (default value_provider create path)"
consumers = ["clone"]
recovery = "re-mint"
state = "active"
policy = { allowed_repos = "*", blast_radius = "low" }
rotation = { class = "token", staged = true }
verify = { probe = "forge-auth" }
surfaces = [ { type = "woodpecker-org-secret", events = ["push"] }, { type = "store" } ]

[clone_key]
family = "mgf"
kind = "ssh-deploy-key"
purpose = "fleet clone key (default pubkey derive path)"
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 = ["repo-x"], readonly = true, title = "clone" }, { type = "store" } ]

[local_tok]
family = "mgf"
kind = "api-token"
purpose = "local-file cache entry (materialize delegation)"
consumers = ["workstation"]
recovery = "re-mint bare-value"
state = "active"
policy = { allowed_repos = "*", blast_radius = "low" }
rotation = { class = "token", staged = false }
verify = { probe = "forge-auth" }
surfaces = [ { type = "local-file", repo = "mgf", path = "tokens/t.txt", mode = "0600" }, { type = "store" } ]
"""


def _env(tmp_path: Path):
    fed = tmp_path / "fed"
    (fed / "mgf-standard").mkdir(parents=True)
    store = tmp_path / "store"
    (store / "secrets").mkdir(parents=True)
    founder, operator = x25519.Identity.generate(), x25519.Identity.generate()
    okey = tmp_path / "operator.key"
    okey.write_text(str(operator) + "\n", encoding="utf-8")
    okey.chmod(0o600)
    (store / "recipients.txt").write_text(
        f"founder  {founder.to_public()}\noperator {operator.to_public()}\n", encoding="utf-8"
    )
    (fed / "mgf-standard" / "SECRETS.toml").write_text(REGISTRY, encoding="utf-8")
    _put(store, "org_pub", b"org-secret-value")
    _put(store, "local_tok", b"local-token-value")
    # clone_key needs no stored value: deploy-key registration sources the PUBLIC key
    # from a repo that already carries it, never the private half from the store.
    return fed, store, okey


def _put(store: Path, entry_id: str, value: bytes) -> None:
    # recipients=None → read the store's recipients.txt (both test keys).
    store_mod.store_put(
        entry_id,
        value,
        root=store,
        encrypted_at=datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ"),
        family="mgf",
        kind="api-token",
    )


def _rec(reg, fed, store, okey, **clients):
    return Reconciler(reg, fed_root=fed, store_root=store, identity_path=str(okey), **clients)


def test_default_value_provider_creates_from_store(tmp_path) -> None:
    fed, store, okey = _env(tmp_path)
    reg = load([fed / "mgf-standard" / "SECRETS.toml"])
    wp = FakeWoodpecker(org_secrets={}, repos=[])  # org_pub missing → create path
    rec = _rec(reg, fed, store, okey, woodpecker=wp)  # NO value_provider → store_get default
    rec.apply(["woodpecker"], skip_canary=True)
    assert wp.org_secret_states()["org_pub"].events == frozenset({"push"})


def test_local_surface_materialize(tmp_path) -> None:
    fed, store, okey = _env(tmp_path)
    reg = load([fed / "mgf-standard" / "SECRETS.toml"])
    rec = _rec(reg, fed, store, okey)
    plan = rec.plan(["local"])
    assert [(a.op, a.id) for a in plan.actions] == [("materialize", "local_tok")]
    rec.apply(["local"], skip_canary=True)
    target = fed / "mgf" / "my_stuff" / "tokens" / "t.txt"
    assert target.is_file()
    assert oct(target.stat().st_mode & 0o777) == "0o600"
    # idempotent: the file is now present at the declared mode.
    assert rec.plan(["local"]).is_empty


def test_forge_plan_unverifiable_note(tmp_path) -> None:
    fed, store, okey = _env(tmp_path)
    reg = load([fed / "mgf-standard" / "SECRETS.toml"])
    forge = FakeForge({}, rate_limited={"repo-x"})
    rec = _rec(reg, fed, store, okey, forge=forge)
    plan = rec.plan(["forge"])
    assert plan.is_empty  # a rate-limited repo yields NO register action…
    assert any(n.kind == "unverifiable" and "repo-x" in n.message for n in plan.notes)  # …a note


def test_host_missing_and_unreachable_notes(tmp_path) -> None:
    reg = load(
        [
            _write(
                tmp_path,
                """\
[hf]
family = "mgf"
kind = "password"
purpose = "host file"
consumers = ["srv"]
recovery = "reset"
state = "active"
policy = { allowed_repos = "*", blast_radius = "low" }
rotation = { class = "password", staged = true }
verify = { probe = "server-env-present" }
surfaces = [
  { type = "host-file", host = "h1", path = "/a", mode = "0600", owner = "root" },
  { type = "host-file", host = "h2", path = "/b", mode = "0600", owner = "root" },
]
""",
            )
        ]
    )
    hosts = FakeHost(
        {
            ("h1", "/a"): HostStat("missing"),
            ("h2", "/b"): HostStat("unreachable", detail="permission denied"),
        }
    )
    rec = Reconciler(reg, fed_root=tmp_path, hosts=hosts)
    plan = rec.plan(["hosts"])
    assert plan.is_empty  # sync never creates host contents in P3
    kinds = {(n.kind) for n in plan.notes}
    assert "skip" in kinds and "unverifiable" in kinds


def _write(tmp_path: Path, text: str) -> Path:
    p = tmp_path / "SECRETS.toml"
    p.write_text(text, encoding="utf-8")
    return p
