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

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

ROOT = Path(__file__).resolve().parents[1]
PROJECT_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_active(manifest: dict, key: str) -> Path:
    value = (manifest.get("active_paths") or {}).get(key)
    if not isinstance(value, str) or not value:
        raise RuntimeError(f"active_paths.{key} is missing")
    path = Path(value)
    if not path.is_absolute():
        path = ROOT / path
    try:
        path.resolve().relative_to(ROOT.resolve())
    except ValueError as exc:
        raise RuntimeError(f"active path escapes project: {key}") from exc
    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:
    project = json.loads(PROJECT_MANIFEST.read_text(encoding="utf-8"))
    promotion_path = resolve_active(project, "promotion_receipt")
    brief_path = resolve_active(project, "story_brief")
    output = resolve_active(project, "metadata")
    receipt_path = resolve_active(project, "metadata_receipt")
    if output.exists() or receipt_path.exists():
        raise RuntimeError("metadata production output already exists and requires audit/invalidation")
    promotion = json.loads(promotion_path.read_text(encoding="utf-8"))
    brief = json.loads(brief_path.read_text(encoding="utf-8"))
    title = project.get("story_title")
    if promotion.get("status") != "completed" or promotion.get("verified") is not True:
        raise RuntimeError("promotion is absent or not verified")
    if promotion.get("canonical_title") != title or brief.get("canonical_title") != title:
        raise RuntimeError("canonical title drift detected")
    youtube_title = f"Truyện Audio | {str(title).upper()} (Full) | Gác Mái Audio"
    if not 2 <= len(youtube_title) <= 100:
        raise RuntimeError(f"YouTube title length invalid: {len(youtube_title)}")
    summary = (
        "Tống Vãn Ninh là chuyên gia phục chế vải cổ tại thành phố Lâm Giang. "
        "Khi một chiếc áo cưới lụa ngà vô danh được gửi đến bảo tàng giữa mùa mưa, "
        "cô phát hiện dưới lớp lót có những mũi chỉ gợi lại người mẹ đã mất. "
        "Để bảo vệ hiện vật và xưởng may Túc Vũ, cô buộc phải hợp tác với kiến trúc sư "
        "Cố Trạch Xuyên - người luôn làm đúng nhưng hiếm khi giải thích. Giữa hạn triển lãm, "
        "áp lực truyền thông và những ký ức chưa từng được gọi tên, liệu họ có thể học cách "
        "nói ra điều cần giữ và trao cho nhau quyền lựa chọn?"
    )
    content = f"""{youtube_title}

Bạn đang lắng nghe {title} tại Gác Mái Audio.

Tóm tắt truyện:
{summary}

🎧 Tên truyện: {title}
🎙 Giọng đọc: Gác Mái Audio
📚 Thể loại: Ngôn tình đô thị, bí ẩn gia đình, chữa lành, drama nhẹ
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.

#GacMaiAudio #TruyenAudio #NgheTruyen #TruyenHay #TruyenDemKhuya #TruyenNgonTinh
"""
    data = content.encode("utf-8")
    atomic_write(output, data)
    receipt = {
        "status": "completed", "verified": True,
        "source_canon_sha256": promotion["canon_sha256"],
        "promotion_receipt": {"path": str(promotion_path), "sha256": sha256(promotion_path)},
        "input_path": str(brief_path), "input_sha256": sha256(brief_path),
        "output_path": str(output), "artifact_sha256": sha256(output), "bytes": len(data),
        "youtube_title": youtube_title, "youtube_title_length": len(youtube_title),
        "canonical_title": title, "spoiler_safe": True,
        "hashtags": ["#GacMaiAudio", "#TruyenAudio", "#NgheTruyen", "#TruyenHay", "#TruyenDemKhuya", "#TruyenNgonTinh"],
    }
    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), "sha256": receipt["artifact_sha256"], "receipt": str(receipt_path)}, ensure_ascii=False))
    return 0


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