#!/usr/bin/env python3
"""arq-deploy-staging v0 · staging-only deploy dispatch · ARQERA runtime primitive.

Per operator directive 2026-05-20: capability-primitives-activation-wave-v0 ·
dogfood-driven · use-or-update over invention.

Wraps `arq-github workflow dispatch --workflow deploy-staging.yml --ref main`
with substrate-attest + STAGING-ONLY scope bound. Refuses any attempt to
dispatch production workflows.

Authority scope (bounded · per operator directive):
  ALLOWED:  deploy-staging.yml dispatches with substrate-approval-ref
  DENIED:   deploy-production-gke.yml · any non-staging workflow ·
            secret-update · cluster-mutation
"""
from __future__ import annotations

import argparse
import json
import os
import re
import shutil
import subprocess
import sys
from datetime import datetime, timezone

POLICY_VERSION = "arq-deploy-staging-v0-2026-05-20"
# Portable binary resolution: env override → PATH lookup → None.
# When None, downstream call sites emit a loud stderr WARN and skip · never silent.
TWIN_BIN = os.environ.get("TWIN_BIN") or shutil.which("twin")
ARQ_GITHUB_BIN = os.environ.get("ARQ_GITHUB_BIN") or shutil.which("arq-github")

STAGING_ONLY_WORKFLOW = "deploy-staging.yml"


def now_iso() -> str:
    return datetime.now(timezone.utc).isoformat()


def now_compact() -> str:
    return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H%M%SZ")


_EMIT_WARN_LOGGED = False


def emit_act(act_type: str, ref: str, payload: dict) -> None:
    global _EMIT_WARN_LOGGED
    if not TWIN_BIN or not os.path.exists(TWIN_BIN):
        if not _EMIT_WARN_LOGGED:
            print(
                "arq-deploy-staging: WARN twin binary not found "
                "(set TWIN_BIN or install `twin` on PATH) · audit acts will be skipped",
                file=sys.stderr,
            )
            _EMIT_WARN_LOGGED = True
        return
    try:
        subprocess.run(
            [TWIN_BIN, "--use-keychain", "act", "emit", "act", act_type,
             f"{ref}-{now_compact()}",
             "--payload", json.dumps({**payload, "policy": POLICY_VERSION, "issued_at": now_iso()})],
            check=False, timeout=10, capture_output=True,
        )
    except Exception as e:
        print(f"arq-deploy-staging: emit_act warning: {e}", file=sys.stderr)


def validate_approval_ref(ref: str) -> bool:
    return bool(re.match(r"^arq://act/[a-z0-9_]+/[a-z0-9_\-:.]+$", ref, re.IGNORECASE))


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--substrate-approval-ref", required=True,
                        help="arq://act/<class>/<ref> authorising this dispatch")
    parser.add_argument("--reason", required=True, help="Audit-trail justification")
    parser.add_argument("--round", default=None, help="Deploy round label (e.g. r9)")
    args = parser.parse_args()

    if not validate_approval_ref(args.substrate_approval_ref):
        print(f"arq-deploy-staging: invalid substrate-approval-ref format: {args.substrate_approval_ref}", file=sys.stderr)
        return 64

    if "production" in args.substrate_approval_ref.lower():
        print(f"arq-deploy-staging: DENIED — production-tagged approval refs not allowed here", file=sys.stderr)
        emit_act("arq_deploy_staging_denied", args.round or "no-round", {
            "reason": "production_approval_ref_blocked",
            "supplied_ref": args.substrate_approval_ref,
        })
        return 99

    round_label = args.round or f"adhoc-{now_compact()}"
    emit_act("arq_deploy_staging_initiated", round_label, {
        "workflow": STAGING_ONLY_WORKFLOW,
        "ref_branch": "main",
        "substrate_approval_ref": args.substrate_approval_ref,
        "reason": args.reason[:500],
    })

    if not ARQ_GITHUB_BIN:
        print(
            "arq-deploy-staging: ERROR arq-github binary not found "
            "(set ARQ_GITHUB_BIN or install `arq-github` on PATH) · cannot dispatch deploy workflow",
            file=sys.stderr,
        )
        return 99
    r = subprocess.run(
        [ARQ_GITHUB_BIN, "workflow", "dispatch",
         "--workflow", STAGING_ONLY_WORKFLOW,
         "--ref", "main",
         "--substrate-approval-ref", args.substrate_approval_ref,
         "--reason", args.reason],
        check=False, capture_output=True, text=True,
    )
    print(r.stdout, end="")
    if r.stderr:
        print(r.stderr, end="", file=sys.stderr)

    if r.returncode == 0:
        emit_act("arq_deploy_staging_dispatched", round_label, {
            "workflow": STAGING_ONLY_WORKFLOW,
            "ref_branch": "main",
            "exit_code": r.returncode,
            "stdout_preview": r.stdout[:500],
        })
        print(f"arq-deploy-staging: ✓ {round_label} dispatched", file=sys.stderr)
    else:
        emit_act("arq_deploy_staging_dispatch_failed", round_label, {
            "workflow": STAGING_ONLY_WORKFLOW,
            "ref_branch": "main",
            "exit_code": r.returncode,
            "stdout_preview": r.stdout[:500],
            "stderr_preview": r.stderr[:500],
        })
        print(f"arq-deploy-staging: ✗ dispatch failed exit={r.returncode}", file=sys.stderr)
    return r.returncode


if __name__ == "__main__":
    raise SystemExit(main())
