#!/usr/bin/env python3
"""Build the exact no-send packet for Leo's unseen Telegram reasoning chain."""

from __future__ import annotations

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

try:
    import verify_leo_unseen_reasoning_chain as unseen
except ImportError:  # pragma: no cover - imported as scripts.* in tests
    from scripts import verify_leo_unseen_reasoning_chain as unseen

SCHEMA = "livingip.telegramVisibleUnseenChainPacket.v2"
REPO_ROOT = Path(__file__).resolve().parents[1]
REPORT_DIR = Path("docs/reports/leo-working-state-20260709")
DEFAULT_HANDLER_RECEIPT = REPORT_DIR / "leo-unseen-reasoning-chain-canary-current.json"
DEFAULT_OUT = REPORT_DIR / "telegram-visible-unseen-chain-authorization-packet-current.json"
DEFAULT_MARKDOWN_OUT = REPORT_DIR / "telegram-visible-unseen-chain-authorization-packet-current.md"
DEFAULT_CAPTURE_RECEIPT = REPORT_DIR / "telegram-visible-unseen-chain-capture-receipt-current.json"
DEFAULT_PREFLIGHT = REPORT_DIR / "telegram-visible-unseen-chain-preflight-current.json"
DEFAULT_POSTFLIGHT = REPORT_DIR / "telegram-visible-unseen-chain-postflight-current.json"
DEFAULT_CHAT_ID = "-5146042086"
DEFAULT_CHAT_LABEL = "Leo"
DEFAULT_PROOF_DIR = "outputs/telegram-visible-unseen-chain-20260715"
DEFAULT_MANIFEST_SQL = Path("ops/postgres_parity_manifest.sql")
READ_ONLY_DB_ROLE = "pg_read_all_data"
DEFAULT_CODEX_THREAD_ID = "019f6350-3350-7040-b223-c5c22673fece"
TOOLING_PATHS = {
    "packet_builder": Path("scripts/build_telegram_visible_unseen_chain_packet.py"),
    "state_collector": Path("scripts/collect_telegram_visible_unseen_chain_state.py"),
    "capture_verifier": Path("scripts/verify_telegram_visible_unseen_chain.py"),
}


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


def _sha256_bytes(value: bytes) -> str:
    return hashlib.sha256(value).hexdigest()


def _sha256_file(path: Path) -> str:
    return _sha256_bytes(path.read_bytes())


def _canonical_sha256(value: Any) -> str:
    encoded = json.dumps(value, sort_keys=True, separators=(",", ":")).encode("utf-8")
    return _sha256_bytes(encoded)


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 exact_messages() -> list[dict[str, Any]]:
    messages = []
    for sequence, prompt in enumerate(unseen.PROMPTS, start=1):
        message = str(prompt["message"])
        messages.append(
            {
                "sequence": sequence,
                "prompt_id": prompt["id"],
                "dimension": prompt["dimension"],
                "message": message,
                "message_sha256": _sha256_bytes(message.encode("utf-8")),
                "wait_for_visible_reply_before_next": True,
            }
        )
    return messages


def tooling_binding(repo_root: Path = REPO_ROOT) -> dict[str, dict[str, Any]]:
    return {name: {"path": str(path), "sha256": _sha256_file(repo_root / path)} for name, path in TOOLING_PATHS.items()}


def manifest_binding(repo_root: Path = REPO_ROOT) -> dict[str, Any]:
    return {
        "path": str(DEFAULT_MANIFEST_SQL),
        "sha256": _sha256_file(repo_root / DEFAULT_MANIFEST_SQL),
        "execution_contract": {
            "database": "teleo",
            "authenticated_role": "postgres",
            "effective_role": READ_ONLY_DB_ROLE,
            "default_transaction_read_only": "on",
            "transaction_read_only": "on",
            "psql_rc_disabled": True,
            "arbitrary_manifest_override_allowed": False,
        },
    }


def _handler_checks(receipt: dict[str, Any]) -> dict[str, bool]:
    safety = receipt.get("safety_gate") if isinstance(receipt.get("safety_gate"), dict) else {}
    safety_checks = safety.get("checks") if isinstance(safety.get("checks"), dict) else {}
    database = receipt.get("database") if isinstance(receipt.get("database"), dict) else {}
    prompt_ids = [str(item["id"]) for item in unseen.PROMPTS]
    return {
        "handler_receipt_passed": receipt.get("status") == "pass",
        "handler_receipt_schema_supported": receipt.get("schema") == unseen.SCHEMA,
        "handler_prompt_ids_exact": receipt.get("prompt_ids") == prompt_ids,
        "handler_outcomes_all_pass": bool(receipt.get("outcomes"))
        and all(value is True for value in receipt.get("outcomes", {}).values()),
        "handler_checks_all_pass": bool(receipt.get("checks"))
        and all(value is True for value in receipt.get("checks", {}).values()),
        "handler_safety_gate_passed": safety.get("status") == "pass",
        "handler_proved_no_telegram_post": safety_checks.get("no_telegram_post") is True,
        "handler_proved_read_only_tool_traces": safety_checks.get("all_tool_traces_read_only_and_bound") is True,
        "handler_proved_unchanged_fingerprint": database.get("fingerprint_unchanged") is True
        and isinstance(database.get("fingerprint_sha256"), str)
        and len(database["fingerprint_sha256"]) == 64,
        "handler_tier_remains_below_telegram_visible": "Telegram-visible message delivery"
        in (receipt.get("claim_ceiling") or {}).get("not_proven", []),
    }


def _authorization_text(*, chat_label: str, chat_id: str, messages: list[dict[str, Any]]) -> str:
    quoted = " ".join(f"[{item['prompt_id']}] {json.dumps(item['message'], ensure_ascii=True)}" for item in messages)
    return (
        "I authorize Codex to use the already-authenticated Chrome Telegram UI to send exactly these three "
        f"messages, in order and with no additional messages, to the Telegram group {chat_label} (chat ID "
        f"{chat_id}), waiting for Leo's visible reply after each turn: {quoted} Capture the visible replies, "
        "message IDs, timestamps, screenshot and accessibility evidence, plus an independently retained Chrome "
        "control provenance receipt bound to the Codex rollout's user-authorization and Chrome tool events; "
        "perform only read-only DB/service "
        "readbacks; do not use the Bot API; do not stage, approve, apply, or otherwise mutate knowledge."
    )


def build_packet(
    *,
    handler_receipt_path: Path = DEFAULT_HANDLER_RECEIPT,
    chat_id: str = DEFAULT_CHAT_ID,
    chat_label: str = DEFAULT_CHAT_LABEL,
    proof_dir: str = DEFAULT_PROOF_DIR,
    codex_thread_id: str = DEFAULT_CODEX_THREAD_ID,
    git_sha: str | None = None,
) -> dict[str, Any]:
    handler_receipt = _load_json(handler_receipt_path)
    messages = exact_messages()
    handler_checks = _handler_checks(handler_receipt)
    target = {
        "platform": "telegram",
        "chat_label": chat_label,
        "chat_id": chat_id,
        "allowed_transport": "authenticated_chrome_telegram_ui",
        "forbidden_transports": ["telegram_bot_api", "copied_transcript", "handler_substitution"],
        "message_count": len(messages),
        "expected_prompt_ids": [item["prompt_id"] for item in messages],
    }
    handler_binding = {
        "path": str(handler_receipt_path),
        "sha256": _sha256_file(handler_receipt_path),
        "schema": handler_receipt.get("schema"),
        "proof_tier": handler_receipt.get("proof_tier"),
        "remote_run_id": handler_receipt.get("remote_run_id"),
        "deployed_git_head": handler_receipt.get("deployed_git_head"),
        "fingerprint_sha256": (handler_receipt.get("database") or {}).get("fingerprint_sha256"),
    }
    tooling = tooling_binding()
    manifest = manifest_binding()
    browser_provenance_contract = {
        "schema": "livingip.authenticatedChromeTelegramCaptureProvenance.v1",
        "capture_channel": "codex_chrome_extension",
        "requires_preflight_challenge_nonce": True,
        "requires_codex_rollout_log_outside_evidence_root": True,
        "requires_chrome_backend_tool_receipts": True,
        "requires_provenance_sha256_in_final_chrome_tool_receipt": True,
        "requires_codex_user_message_authorization_receipt": True,
        "requires_browser_session_tab_and_capture_identifiers": True,
        "requires_telegram_web_origin_and_chat_identity": True,
        "requires_hashes_for_every_screenshot_and_accessibility_artifact": True,
    }
    protocol = {
        "target": target,
        "exact_messages": messages,
        "handler_binding": handler_binding,
        "tooling_binding": tooling,
        "manifest_binding": manifest,
        "browser_provenance_contract": browser_provenance_contract,
        "operator_context": {
            "codex_thread_id": codex_thread_id,
            "authorization_source": "codex_platform_user_message",
        },
        "state_contract": {
            "preflight": "two identical repeatable-read read-only canonical fingerprints",
            "postflight": "same canonical fingerprint plus independent selected-object readback",
            "service": "same active gateway process before and after",
            "ordering": "preflight < authorization < send1 < reply1 < send2 < reply2 < send3 < reply3 < final/postflight",
        },
    }
    protocol_sha256 = _canonical_sha256(protocol)
    checks = {
        **handler_checks,
        "exact_three_turn_sequence": len(messages) == 3 and [item["sequence"] for item in messages] == [1, 2, 3],
        "exact_prompts_imported_from_handler_verifier": [item["message"] for item in messages]
        == [item["message"] for item in unseen.PROMPTS],
        "first_prompt_supplies_no_row_id": unseen.UUID_RE.search(messages[0]["message"]) is None,
        "authenticated_chrome_is_only_send_transport": target["allowed_transport"]
        == "authenticated_chrome_telegram_ui",
        "canonical_manifest_path_and_sha_bound": manifest == manifest_binding(),
        "database_session_and_role_fail_closed_read_only": manifest["execution_contract"]["effective_role"]
        == READ_ONLY_DB_ROLE
        and manifest["execution_contract"]["default_transaction_read_only"] == "on"
        and manifest["execution_contract"]["transaction_read_only"] == "on"
        and manifest["execution_contract"]["arbitrary_manifest_override_allowed"] is False,
        "independent_browser_provenance_required": browser_provenance_contract[
            "requires_codex_rollout_log_outside_evidence_root"
        ]
        is True,
        "packet_does_not_send": True,
        "packet_does_not_mutate_database": True,
    }
    ready = all(checks.values())
    authorization_text = _authorization_text(chat_label=chat_label, chat_id=chat_id, messages=messages)
    proof_paths = {
        "preflight_json": str(DEFAULT_PREFLIGHT),
        "postflight_json": str(DEFAULT_POSTFLIGHT),
        "capture_receipt_json": str(DEFAULT_CAPTURE_RECEIPT),
        "capture_json": f"{proof_dir}/capture.json",
        "turn_screenshots": [f"{proof_dir}/turn-{index}.png" for index in range(1, 4)],
        "turn_accessibility": [f"{proof_dir}/turn-{index}-accessibility.txt" for index in range(1, 4)],
        "final_screenshot": f"{proof_dir}/final.png",
        "final_accessibility": f"{proof_dir}/final-accessibility.txt",
        "browser_provenance": f"{proof_dir}/browser-provenance.json",
    }
    return {
        "schema": SCHEMA,
        "generated_at_utc": datetime.now(timezone.utc).isoformat(),
        "mode": "telegram_visible_unseen_chain_exact_packet_not_sent",
        "packet_generation_git_sha": git_sha if git_sha is not None else current_git_sha(),
        "protocol_sha256": protocol_sha256,
        "protocol": protocol,
        "ready_to_request_action_time_authorization": ready,
        "authorization_gate_status": "ready_to_request_exact_authorization" if ready else "not_ready",
        "telegram_visible_messages_sent": False,
        "telegram_visible_message_authorization_present": False,
        "production_apply_executed": False,
        "mutates_db": False,
        "target": target,
        "exact_messages": messages,
        "handler_receipt_binding": handler_binding,
        "tooling_binding": tooling,
        "manifest_binding": manifest,
        "browser_provenance_contract": browser_provenance_contract,
        "operator_context": protocol["operator_context"],
        "checks": checks,
        "expected_proof_paths_after_authorized_run": proof_paths,
        "explicit_operator_authorization_text": authorization_text,
        "clear_CTA": (
            "Reply with the exact authorization sentence in this packet. That sentence names the destination, "
            "transport, complete message bodies, ordering, evidence, and no-mutation boundary."
        ),
        "next_non_user_action_after_authorization": [
            "Re-run the zero-mutation preflight and confirm its packet file hash is current.",
            "Use authenticated Chrome only and verify the Leo chat ID before typing anything.",
            "Send one exact message, wait for Leo's visible reply, then continue to the next exact message.",
            "Capture message IDs, timestamps, screenshot, accessibility text, and the Chrome-control provenance receipt without copying handler output.",
            "Retain the Codex rollout path whose Chrome tool receipt contains the provenance SHA256.",
            "Extract the selected DB object reference and run the read-only postflight with that reference.",
            "Run the Telegram-visible verifier and accept T3 only if every visible and state check passes.",
        ],
        "claim_ceiling": {
            "current_tier": "T0_spec_plus_prior_T2_handler_evidence",
            "required_tier": "T3_live_readonly",
            "proven": "The exact three-turn Chrome send packet is bound to a passing no-send handler receipt.",
            "not_proven": [
                "Telegram-visible delivery of these three messages",
                "Telegram-visible replies from Leo",
                "post-send canonical fingerprint equality",
            ],
        },
    }


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:
    target = data["target"]
    lines = [
        "# Telegram-Visible Unseen Chain Authorization Packet",
        "",
        f"Generated UTC: `{data['generated_at_utc']}`",
        f"Protocol SHA256: `{data['protocol_sha256']}`",
        f"Ready to request action-time authorization: `{data['ready_to_request_action_time_authorization']}`",
        f"Telegram-visible messages sent: `{data['telegram_visible_messages_sent']}`",
        f"Mutates DB: `{data['mutates_db']}`",
        "",
        "## Exact Destination",
        "",
        f"- Chat: `{target['chat_label']}` (`{target['chat_id']}`)",
        f"- Transport: `{target['allowed_transport']}`",
        "",
        "## Exact Messages",
        "",
    ]
    for item in data["exact_messages"]:
        lines.extend(
            [
                f"### {item['sequence']}. {item['prompt_id']}",
                "",
                item["message"],
                "",
                f"SHA256: `{item['message_sha256']}`",
                "",
            ]
        )
    manifest = data["manifest_binding"]
    execution = manifest["execution_contract"]
    lines.extend(
        [
            "## Read-Only State Contract",
            "",
            f"- Manifest: `{manifest['path']}`",
            f"- Manifest SHA256: `{manifest['sha256']}`",
            f"- Effective DB role: `{execution['effective_role']}`",
            f"- Transaction read only: `{execution['transaction_read_only']}`",
            f"- Arbitrary manifest override allowed: `{execution['arbitrary_manifest_override_allowed']}`",
            "",
            "## Independent Capture Contract",
            "",
            f"- Codex thread: `{data['operator_context']['codex_thread_id']}`",
            "- Authorization must be an exact platform user-message event in that thread's rollout.",
            "- Each turn and final artifact must be bound by Chrome-backend tool receipts in that rollout.",
            "",
            "## Checks",
            "",
        ]
    )
    lines.extend(f"- `{key}`: `{value}`" for key, value in sorted(data["checks"].items()))
    lines.extend(
        [
            "",
            "## Exact Action-Time Authorization",
            "",
            data["explicit_operator_authorization_text"],
            "",
            "## Clear CTA",
            "",
            data["clear_CTA"],
            "",
            "## Claim Ceiling",
            "",
            f"Current tier: `{data['claim_ceiling']['current_tier']}`",
            f"Required tier: `{data['claim_ceiling']['required_tier']}`",
            "",
        ]
    )
    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("--handler-receipt", type=Path, default=DEFAULT_HANDLER_RECEIPT)
    parser.add_argument("--chat-id", default=DEFAULT_CHAT_ID)
    parser.add_argument("--chat-label", default=DEFAULT_CHAT_LABEL)
    parser.add_argument("--proof-dir", default=DEFAULT_PROOF_DIR)
    parser.add_argument("--out", type=Path, default=DEFAULT_OUT)
    parser.add_argument("--markdown-out", type=Path, default=DEFAULT_MARKDOWN_OUT)
    return parser.parse_args(argv)


def main(argv: list[str] | None = None) -> int:
    args = parse_args(argv)
    data = build_packet(
        handler_receipt_path=args.handler_receipt,
        chat_id=args.chat_id,
        chat_label=args.chat_label,
        proof_dir=args.proof_dir,
    )
    write_json(args.out, data)
    write_markdown(args.markdown_out, data)
    print(
        json.dumps(
            {
                "out": str(args.out),
                "markdown_out": str(args.markdown_out),
                "ready_to_request_action_time_authorization": data["ready_to_request_action_time_authorization"],
                "telegram_visible_messages_sent": False,
            },
            indent=2,
            sort_keys=True,
        )
    )
    return 0 if data["ready_to_request_action_time_authorization"] else 2


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