#!/usr/bin/env python3
from __future__ import annotations

import datetime
import json
import os
import subprocess
import sys
import time
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
MANIFEST = ROOT / "script/project-manifest.json"
TTS_RECEIPT = ROOT / "log/tts-production.json"
TTS_PARTIAL = ROOT / "audio/tts-partial.json"


def read_json(path: Path) -> dict:
    return json.loads(path.read_text(encoding="utf-8"))


def write_manifest(mutator) -> None:
    value = read_json(MANIFEST)
    mutator(value)
    temp = MANIFEST.with_name(".project-manifest.json.continue.tmp")
    temp.write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    with temp.open("rb") as handle:
        os.fsync(handle.fileno())
    os.replace(temp, MANIFEST)


def main() -> int:
    deadline = time.monotonic() + 5 * 60 * 60
    last_count = -1
    last_progress = time.monotonic()
    while True:
        if TTS_RECEIPT.exists():
            receipt = read_json(TTS_RECEIPT)
            status = receipt.get("status")
            if status == "completed" and receipt.get("verified") is True:
                break
            if status in {"failed", "cancelled"}:
                raise RuntimeError(f"TTS terminal failure: {receipt}")
        if TTS_PARTIAL.exists():
            partial = read_json(TTS_PARTIAL)
            count = int(partial.get("completed_count", 0))
            if count != last_count:
                print(json.dumps({"stage": "tts", "completed_count": count, "planned_count": partial.get("planned_count")}), flush=True)
                last_count = count
                last_progress = time.monotonic()
            elif time.monotonic() - last_progress > 20 * 60:
                raise RuntimeError(f"TTS made no checkpoint progress for 20 minutes at {count}")
        if time.monotonic() >= deadline:
            raise RuntimeError("TTS continuation deadline exceeded")
        time.sleep(30)

    def mark_tts(manifest: dict) -> None:
        now = datetime.datetime.now(datetime.timezone.utc).isoformat()
        receipt = read_json(TTS_RECEIPT)
        manifest["steps"]["tts"] = "completed"
        manifest["tts"] = {
            "status": "completed", "verified": True,
            "receipt": manifest["active_paths"]["tts_receipt"],
            "artifact_sha256": receipt["artifact_sha256"],
            "duration_seconds": receipt["duration_seconds"],
            "segment_count": receipt["segment_count"], "completed_at": now,
        }
        manifest["updated_at"] = now
    write_manifest(mark_tts)

    subprocess.run([sys.executable, "script/run-render-stage.py", "footage"], cwd=ROOT, check=True)

    def mark_footage(manifest: dict) -> None:
        now = datetime.datetime.now(datetime.timezone.utc).isoformat()
        manifest["steps"]["footage"] = "rendered_pending_visual_qa"
        manifest["updated_at"] = now
    write_manifest(mark_footage)

    subprocess.run([sys.executable, "script/extract-video-qa.py", "footage"], cwd=ROOT, check=True)
    print(json.dumps({"status": "completed_pending_footage_visual_review", "tts_receipt": str(TTS_RECEIPT), "footage_receipt": str(ROOT / "log/footage-job.json"), "qa_extraction": str(ROOT / "log/footage-check/extraction.json")}, ensure_ascii=False), flush=True)
    return 0


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except Exception as exc:
        print(json.dumps({"status": "failed", "verified": False, "error": f"{type(exc).__name__}: {exc}"}, ensure_ascii=False), file=sys.stderr, flush=True)
        raise SystemExit(1)
