#!/usr/bin/env python3
import hashlib
import json
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path

PROJECT = Path(__file__).resolve().parents[1]
SCRIPT = PROJECT / "script"
STORY = PROJECT / "story"
MANIFEST = SCRIPT / "project-manifest.json"
PLAN = SCRIPT / "production-plan.json"


def run(path):
    return subprocess.run([sys.executable, "-B", str(path)], cwd=PROJECT).returncode


def sha(path):
    return hashlib.sha256(path.read_bytes()).hexdigest()


def main():
    before = sha(MANIFEST)
    if run(SCRIPT / "validate-story.py") or run(SCRIPT / "validate-originality.py"):
        if sha(MANIFEST) != before:
            raise RuntimeError("manifest changed during failed promotion")
        raise SystemExit("Story promotion blocked: validation failed")
    story = json.loads((STORY / "promotion-report.json").read_text())
    originality = json.loads((STORY / "originality-report.json").read_text())
    plan = json.loads(PLAN.read_text())
    current_authority = {
        "outline_sha256": sha(SCRIPT / "outline.json"),
        "identity_registry_sha256": sha(SCRIPT / "identity-registry.json"),
        "reveal_ledger_sha256": sha(SCRIPT / "reveal-ledger.json"),
        "story_brief_sha256": sha(SCRIPT / "story-brief.json"),
    }
    if current_authority != plan.get("authority_hashes"):
        raise SystemExit("Story promotion blocked: authority lock changed")
    if story.get("verified") is not True or originality.get("verified") is not True or story.get("spoken_sha256") != originality.get("source_sha256"):
        raise SystemExit("Story promotion blocked: report mismatch")
    promoted_at = datetime.now(timezone.utc).isoformat()
    manifest = json.loads(MANIFEST.read_text())
    plan.update({"status": "story_promoted_ready_for_tts", "canon_sha256": story["spoken_sha256"], "story_words": story["total_words"], "tts_words_per_minute": 231, "story_duration_estimate_minutes": story["estimated_minutes_at_baseline"], "promoted_at": promoted_at})
    manifest.update({"status": "story_promoted", "canon_version": 1, "canon_hash": story["spoken_sha256"], "story_word_count": story["total_words"], "tts_words_per_minute": 231, "story_duration_estimate_minutes": story["estimated_minutes_at_baseline"], "authority_hashes_promoted": current_authority, "updated_at": promoted_at})
    manifest["steps"]["story"] = "completed"
    PLAN.write_text(json.dumps(plan, ensure_ascii=False, indent=2) + "\n")
    manifest["production_plan_hash"] = "sha256:" + sha(PLAN)
    MANIFEST.write_text(json.dumps(manifest, ensure_ascii=False, indent=2) + "\n")
    receipt = {"version": 1, "verified": True, "promoted_canon_sha256": story["spoken_sha256"], "tts_words_per_minute": 231, "story_duration_estimate_minutes": story["estimated_minutes_at_baseline"], "story_report_sha256": sha(STORY / "promotion-report.json"), "originality_report_sha256": sha(STORY / "originality-report.json"), "production_plan_sha256": sha(PLAN), "authority_hashes": current_authority, "promoted_at": promoted_at}
    (STORY / "promotion-receipt.json").write_text(json.dumps(receipt, ensure_ascii=False, indent=2) + "\n")
    print(json.dumps({"promoted": True, "canon_sha256": story["spoken_sha256"], "words": story["total_words"], "estimated_minutes": story["estimated_minutes_at_baseline"]}, ensure_ascii=False))
    return 0

if __name__ == "__main__":
    sys.exit(main())
