#!/usr/bin/env python3
"""Build a non-executed Working Leo production-apply receipt template.

The real production apply receipt must be written only after explicit
authorization and actual apply/postflight/regression execution. This script
prepares the operator-facing template before that boundary: it identifies which
receipt fields are already backed by retained artifacts and which fields must be
filled after the authorized apply window.
"""

from __future__ import annotations

import argparse
import json
import subprocess
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

REPORT_DIR = Path("docs/reports/leo-working-state-20260709")
DEFAULT_RUNBOOK = REPORT_DIR / "working-leo-authorized-apply-runbook-current.json"
DEFAULT_PREFLIGHT_JSON = REPORT_DIR / "working-leo-production-preflight-current.json"
DEFAULT_PREFLIGHT_MD = REPORT_DIR / "working-leo-production-preflight-current.md"
DEFAULT_VALIDATION = REPORT_DIR / "working-leo-production-apply-receipt-validation-current.json"
DEFAULT_OUT = REPORT_DIR / "working-leo-production-apply-receipt-template-current.json"
DEFAULT_MARKDOWN_OUT = REPORT_DIR / "working-leo-production-apply-receipt-template-current.md"


def _load_json(path: Path) -> dict[str, Any]:
    return json.loads(path.read_text(encoding="utf-8"))


def _path_status(path: Path) -> dict[str, Any]:
    exists = path.exists()
    return {"path": str(path), "exists": exists, "bytes": path.stat().st_size if exists else 0}


def current_git_sha(repo_root: Path = Path(".")) -> str:
    proc = subprocess.run(
        ["git", "rev-parse", "HEAD"],
        cwd=repo_root,
        text=True,
        capture_output=True,
        check=False,
    )
    return proc.stdout.strip() if proc.returncode == 0 else ""


def _regression_artifacts(runbook: dict[str, Any]) -> dict[str, str]:
    result: dict[str, str] = {}
    for command in runbook.get("post_apply_regression_commands", []):
        artifact = str(command.get("expected_artifact") or "")
        if artifact and artifact != "terminal pytest output":
            result[str(command.get("id"))] = artifact
    return result


def _rollback_paths(runbook: dict[str, Any]) -> list[str]:
    return [str(entry["path"]) for entry in runbook["phases"]["rollback_order"]]


def _postflight_paths(runbook: dict[str, Any]) -> list[str]:
    return [str(entry["path"]) for entry in runbook["phases"]["postflight_order"]]


def build_template(
    *,
    runbook_path: Path = DEFAULT_RUNBOOK,
    preflight_json_path: Path = DEFAULT_PREFLIGHT_JSON,
    preflight_markdown_path: Path = DEFAULT_PREFLIGHT_MD,
    validation_path: Path = DEFAULT_VALIDATION,
    git_sha: str | None = None,
) -> dict[str, Any]:
    runbook = _load_json(runbook_path)
    preflight = _load_json(preflight_json_path) if preflight_json_path.exists() else {}
    validation = _load_json(validation_path) if validation_path.exists() else {}
    regressions = _regression_artifacts(runbook)
    sha = git_sha if git_sha is not None else current_git_sha()

    receipt_template = {
        "explicit_authorization_record": {
            "authorized": False,
            "fill_after_authorization": True,
            "required_scope": "integrated Working Leo packet set in runbook dependency order",
        },
        "operator_identity": "",
        "git_commit_sha": sha,
        "preflight_output_paths": [str(preflight_json_path), str(preflight_markdown_path)],
        "apply_output_paths": [],
        "postflight_output_paths": [],
        "expected_after_apply_counts": runbook["expected_after_apply_counts"],
        "actual_after_apply_counts": {},
        "telegram_or_handler_regression_paths": [],
        "direct_claim_score_path": regressions.get("direct_claim_strict_score", ""),
        "service_readback": {},
        "cleanup_readback": {},
        "rollback_packet_paths": _rollback_paths(runbook),
        "known_residual_risks": [
            "GCP parity remains separate until access is restored and read-only parity proof is captured.",
            "Any Telegram-visible post-apply proof must be separately authorized at action time.",
        ],
    }

    field_status = {
        "explicit_authorization_record": "must_fill_after_explicit_authorization",
        "operator_identity": "must_fill_after_explicit_authorization",
        "git_commit_sha": "pre_filled_current_head_verify_at_apply_time",
        "preflight_output_paths": (
            "baseline_available_rerun_immediately_before_apply"
            if preflight.get("status") == "pass"
            else "missing_or_failed_preflight_baseline"
        ),
        "apply_output_paths": "must_fill_after_apply_execution",
        "postflight_output_paths": "must_fill_after_postflight_execution",
        "expected_after_apply_counts": "pre_filled_from_authorized_runbook",
        "actual_after_apply_counts": "must_fill_after_postflight_execution",
        "telegram_or_handler_regression_paths": "must_fill_after_post_apply_regression_rerun",
        "direct_claim_score_path": "baseline_available_but_must_rerun_after_apply",
        "service_readback": "must_fill_after_post_apply_service_readback",
        "cleanup_readback": "must_fill_after_post_apply_cleanup_readback",
        "rollback_packet_paths": "pre_filled_from_authorized_runbook",
        "known_residual_risks": "pre_filled_review_after_apply",
    }

    ready_now = [
        field
        for field, status in field_status.items()
        if status.startswith("pre_filled") or status.startswith("baseline_available")
    ]
    must_fill = [field for field, status in field_status.items() if status.startswith("must_fill")]

    return {
        "generated_at_utc": datetime.now(timezone.utc).isoformat(),
        "mode": "receipt_template_not_executed",
        "production_apply_executed": False,
        "valid_production_receipt": False,
        "runbook_path": str(runbook_path),
        "preflight_artifacts": [_path_status(preflight_json_path), _path_status(preflight_markdown_path)],
        "receipt_validation_status_before_apply": validation.get("status", "missing_validation_artifact"),
        "receipt_template": receipt_template,
        "field_status": field_status,
        "ready_or_baseline_fields": ready_now,
        "must_fill_after_authorized_apply": must_fill,
        "postflight_sql_paths_to_run_after_apply": _postflight_paths(runbook),
        "claim_ceiling": (
            "This is a receipt template only. It proves the operator knows which evidence must be captured, but it "
            "does not authorize production apply and does not prove canonical rows were changed."
        ),
    }


def write_json(path: Path, data: dict[str, Any]) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n", encoding="utf-8")


def write_markdown(path: Path, data: dict[str, Any]) -> None:
    lines = [
        "# Working Leo Production Apply Receipt Template",
        "",
        f"Generated UTC: `{data['generated_at_utc']}`",
        f"Mode: `{data['mode']}`",
        f"Production apply executed: `{data['production_apply_executed']}`",
        f"Valid production receipt: `{data['valid_production_receipt']}`",
        f"Receipt validation status before apply: `{data['receipt_validation_status_before_apply']}`",
        "",
        "## Field Status",
        "",
    ]
    for field, status in data["field_status"].items():
        lines.append(f"- `{field}`: `{status}`")
    lines.extend(["", "## Ready Or Baseline Fields", ""])
    lines.extend(f"- `{field}`" for field in data["ready_or_baseline_fields"])
    lines.extend(["", "## Must Fill After Authorized Apply", ""])
    lines.extend(f"- `{field}`" for field in data["must_fill_after_authorized_apply"])
    lines.extend(["", "## Postflight SQL Paths", ""])
    lines.extend(f"- `{path}`" for path in data["postflight_sql_paths_to_run_after_apply"])
    lines.extend(["", "## Claim Ceiling", "", data["claim_ceiling"], ""])
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text("\n".join(lines), encoding="utf-8")


def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--runbook", type=Path, default=DEFAULT_RUNBOOK)
    parser.add_argument("--preflight-json", type=Path, default=DEFAULT_PREFLIGHT_JSON)
    parser.add_argument("--preflight-markdown", type=Path, default=DEFAULT_PREFLIGHT_MD)
    parser.add_argument("--validation", type=Path, default=DEFAULT_VALIDATION)
    parser.add_argument("--out", type=Path, default=DEFAULT_OUT)
    parser.add_argument("--markdown-out", type=Path, default=DEFAULT_MARKDOWN_OUT)
    parser.add_argument("--git-sha", default=None)
    return parser.parse_args(argv)


def main(argv: list[str] | None = None) -> int:
    args = parse_args(argv)
    data = build_template(
        runbook_path=args.runbook,
        preflight_json_path=args.preflight_json,
        preflight_markdown_path=args.preflight_markdown,
        validation_path=args.validation,
        git_sha=args.git_sha,
    )
    write_json(args.out, data)
    write_markdown(args.markdown_out, data)
    print(
        json.dumps(
            {
                "out": str(args.out),
                "markdown_out": str(args.markdown_out),
                "production_apply_executed": data["production_apply_executed"],
                "valid_production_receipt": data["valid_production_receipt"],
                "must_fill_after_authorized_apply": data["must_fill_after_authorized_apply"],
            },
            indent=2,
            sort_keys=True,
        )
    )
    return 0


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