#!/usr/bin/env python3
"""Build a checksum-bound TTS projection from a released paragraph-based story."""
from __future__ import annotations

import argparse
import hashlib
import json
from pathlib import Path


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


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--story", required=True, type=Path)
    parser.add_argument("--expected-story-sha256", required=True)
    parser.add_argument("--output", required=True, type=Path)
    args = parser.parse_args()

    raw = args.story.read_bytes()
    editorial_sha = sha256(raw)
    if editorial_sha != args.expected_story_sha256:
        raise SystemExit("editorial story checksum mismatch")

    story = json.loads(raw)
    parts = story.get("parts", [])
    if [part.get("part") for part in parts] != list(range(1, 13)):
        raise SystemExit("expected ordered parts 1..12")

    projected_parts = []
    paragraph_count = 0
    for part in parts:
        paragraphs = part.get("paragraphs", [])
        if len(paragraphs) != 12 or any(
            not isinstance(text, str) or not text.strip() for text in paragraphs
        ):
            raise SystemExit(f"invalid paragraph inventory in part {part.get('part')}")
        paragraph_count += len(paragraphs)
        projected_parts.append(
            {
                "part": part["part"],
                "narration": "\n\n".join(text.strip() for text in paragraphs),
            }
        )

    projection = {
        "project_id": story["project_id"],
        "title": story["title"],
        "editorial_story_sha256": editorial_sha,
        "parts": projected_parts,
    }
    args.output.parent.mkdir(parents=True, exist_ok=True)
    args.output.write_text(
        json.dumps(projection, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )

    reread = json.loads(args.output.read_text(encoding="utf-8"))
    narration = "\n\n".join(part["narration"].strip() for part in reread["parts"])
    receipt = {
        "status": "passed",
        "editorial_story_sha256": editorial_sha,
        "tts_projection_path": str(args.output),
        "tts_projection_sha256": sha256(args.output.read_bytes()),
        "narration_text_sha256": sha256(narration.encode("utf-8")),
        "parts": len(projected_parts),
        "paragraphs": paragraph_count,
        "spend_lock_rule": (
            "authorize the exact TTS projection SHA because it is the file the runner reads; "
            "retain editorial_story_sha256 as immutable provenance"
        ),
    }
    receipt_path = args.output.with_suffix(args.output.suffix + ".receipt.json")
    receipt_path.write_text(
        json.dumps(receipt, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )
    print(json.dumps(receipt, ensure_ascii=False))


if __name__ == "__main__":
    main()
