from __future__ import annotations

import argparse
import hashlib
import json
import shutil
import subprocess
import sys
from datetime import datetime
from pathlib import Path
from zoneinfo import ZoneInfo

import numpy as np
from PIL import Image
from pypdf import PdfReader


ROOT = Path(__file__).resolve().parent
PDF = ROOT / "paper.pdf"
RENDER_DIR = ROOT / "tmp" / "pdfs" / "current"
REPORT = ROOT / "pdf-render-report.json"
BUNDLED_PDFTOPPM = Path(r"C:\Users\hands\.cache\codex-runtimes\codex-primary-runtime\dependencies\native\poppler\Library\bin\pdftoppm.exe")


def sha256(path: Path) -> str:
    return hashlib.sha256(path.read_bytes()).hexdigest()


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--pdf", default=str(PDF))
    parser.add_argument("--render-dir", default=str(RENDER_DIR))
    parser.add_argument("--report", default=str(REPORT))
    args = parser.parse_args()
    pdf_path = Path(args.pdf).resolve()
    render_dir = Path(args.render_dir).resolve()
    report_path = Path(args.report).resolve()
    errors: list[str] = []
    render_dir.mkdir(parents=True, exist_ok=True)
    for path in render_dir.glob("page-*.png"):
        path.unlink()
    pdftoppm = str(BUNDLED_PDFTOPPM) if BUNDLED_PDFTOPPM.is_file() else shutil.which("pdftoppm")
    if not pdftoppm:
        raise RuntimeError("pdftoppm is unavailable")
    completed = subprocess.run(
        [pdftoppm, "-png", "-r", "150", str(pdf_path), str(render_dir / "page")],
        capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=300, check=False,
    )
    if completed.returncode != 0:
        raise RuntimeError(completed.stderr[-2000:])
    images = sorted(render_dir.glob("page-*.png"))
    reader = PdfReader(str(pdf_path))
    if len(images) != len(reader.pages):
        errors.append("rendered page count differs from PDF page count")
    pages = []
    for index, path in enumerate(images, 1):
        with Image.open(path) as bitmap:
            rgb = np.asarray(bitmap.convert("RGB"), dtype=np.uint8)
        near_white = float((rgb.mean(axis=2) >= 250).mean())
        dark = float((rgb.mean(axis=2) <= 70).mean())
        if near_white > 0.998:
            errors.append(f"page {index} appears blank")
        if dark > 0.75:
            errors.append(f"page {index} appears unexpectedly dark")
        pages.append({
            "page": index, "path": path.relative_to(ROOT).as_posix(), "width": int(rgb.shape[1]),
            "height": int(rgb.shape[0]), "nearWhiteFraction": round(near_white, 6),
            "darkFraction": round(dark, 6), "sha256": sha256(path),
        })
    payload = {
        "schemaVersion": 1,
        "renderedAt": datetime.now(ZoneInfo("Asia/Taipei")).replace(microsecond=0).isoformat(),
        "status": "PASSED" if not errors else "FAILED",
        "renderEngine": "Poppler pdftoppm",
        "renderDpi": 150,
        "pdf": pdf_path.name,
        "pdfSha256": sha256(pdf_path),
        "pages": pages,
        "errors": errors,
    }
    report_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    print(json.dumps({"status": payload["status"], "pages": len(pages), "renderDir": str(render_dir)}, ensure_ascii=False))
    if errors:
        sys.exit(1)


if __name__ == "__main__":
    main()
