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

import datetime
import hashlib
import json
import os
import tempfile
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
MANIFEST = ROOT / "script/project-manifest.json"


def sha256(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as handle:
        for chunk in iter(lambda: handle.read(8 * 1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()


def resolve(manifest: dict, key: str) -> Path:
    value = manifest["active_paths"][key]
    path = Path(value)
    if not path.is_absolute():
        path = ROOT / path
    path.resolve().relative_to(ROOT.resolve())
    return path


def atomic_write(path: Path, data: bytes) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    fd, name = tempfile.mkstemp(prefix=f".{path.name}.", dir=path.parent)
    try:
        with os.fdopen(fd, "wb") as handle:
            handle.write(data); handle.flush(); os.fsync(handle.fileno())
        os.replace(name, path)
    finally:
        if os.path.exists(name): os.unlink(name)


def main() -> int:
    manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
    output = resolve(manifest, "metadata")
    receipt_path = resolve(manifest, "metadata_receipt")
    if output.exists() or receipt_path.exists():
        raise RuntimeError("metadata output/receipt already exists and requires audit/invalidation")
    receipt_keys = ["promotion_receipt", "final_receipt", "final_qa_receipt", "transcode_receipt"]
    receipts = {}
    canon_hash = manifest.get("canon_sha256")
    for key in receipt_keys:
        path = resolve(manifest, key)
        if not path.exists():
            raise RuntimeError(f"required receipt missing: {key}")
        value = json.loads(path.read_text(encoding="utf-8"))
        current = value.get("canon_sha256") if key == "promotion_receipt" else value.get("source_canon_sha256")
        if value.get("status") != "completed" or value.get("verified") is not True or current != canon_hash:
            raise RuntimeError(f"required receipt is not current completed/verified: {key}")
        receipts[key] = {"path": str(path), "sha256": sha256(path)}
    title = "Những Lá Thư Dưới Ghế Cuối"
    youtube_title = "Truyện Audio | NHỮNG LÁ THƯ DƯỚI GHẾ CUỐI (Full) | Gác Mái Audio"
    if len(youtube_title) > 100:
        raise RuntimeError("YouTube title exceeds 100 characters")
    summary = (
        "Tạ Minh Yên là điều phối viên của tuyến xe buýt đêm số 27, một tuyến đường đang đứng trước nguy cơ bị cắt giảm. "
        "Khi những lá thư hành khách để lại hé lộ khoảng trống giữa số liệu vận hành và đời sống thật, cô phải hợp tác với tài xế Trình Hạo Dương để tìm một cách lên tiếng mà không xâm phạm câu chuyện riêng của bất kỳ ai. "
        "Giữa thời hạn đánh giá, áp lực nghề nghiệp và những lời từng không được nói trọn, liệu họ có thể bảo vệ quyền lựa chọn của cộng đồng lẫn cơ hội bắt đầu lại của chính mình?"
    )
    hashtags = ["#GacMaiAudio", "#TruyenAudio", "#NgheTruyen", "#TruyenHay", "#TruyenDemKhuya", "#TruyenNgonTinh"]
    text = "\n".join([
        youtube_title, "", f"Bạn đang lắng nghe {title} tại Gác Mái Audio.", "", "Tóm tắt truyện:", summary, "",
        f"🎧 Tên truyện: {title}", "🎙 Giọng đọc: Gác Mái Audio",
        "📚 Thể loại: Ngôn tình đô thị, chữa lành, drama nghề nghiệp, đời sống cộng đồng", "Tình trạng: Trọn bộ", "",
        "Nếu yêu thích câu chuyện, hãy đăng ký kênh và để lại cảm nhận của bạn dưới phần bình luận.", "",
        "Gác Mái Audio – Lắng nghe một thế giới khác.", "",
        "Nội dung được phát hành độc quyền tại Gác Mái Audio. Vui lòng không sao chép và đăng tải lại dưới bất kỳ hình thức nào.", "",
        " ".join(hashtags), "",
    ])
    data = text.encode("utf-8")
    atomic_write(output, data)
    receipt = {
        "status": "completed", "verified": True, "source_canon_sha256": canon_hash,
        "input_receipts": receipts, "output_path": str(output), "artifact_sha256": sha256(output), "bytes": output.stat().st_size,
        "youtube_title": youtube_title, "youtube_title_length": len(youtube_title), "canonical_title": title,
        "summary_source": "locked brief premise, spoiler-safe paraphrase", "spoiler_safe": True,
        "genre": ["ngôn tình đô thị", "chữa lành", "drama nghề nghiệp", "đời sống cộng đồng"], "hashtags": hashtags,
        "completed_at": datetime.datetime.now(datetime.timezone.utc).isoformat(), "hash_method": "sha256 streaming 8 MiB",
    }
    atomic_write(receipt_path, (json.dumps(receipt, ensure_ascii=False, indent=2) + "\n").encode("utf-8"))
    print(json.dumps({"status": "completed", "verified": True, "output": str(output), "receipt": str(receipt_path)}, ensure_ascii=False))
    return 0


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