"""
PDF → Claude Vision smoke test.

Usage:
    py scripts/vision/pdf-vision-test.py <pdf_path> [--page N] [--dpi 200] [--prompt "..."]

Renders one page of a PDF to PNG via pdf2image (poppler), sends to Claude Opus 4.7
with a vision prompt, prints the response. Designed as the API-path companion to
the OAuth/Read-tool path used by the lfcs-drawing-extract-vision skill.
"""

from __future__ import annotations

import argparse
import base64
import io
import os
import sys
from pathlib import Path

from anthropic import Anthropic
from dotenv import load_dotenv
from pdf2image import convert_from_path
from PIL import Image

DEFAULT_MODEL = "claude-opus-4-7"
DEFAULT_DPI = 200
MAX_EDGE_PX = 1568
JPEG_QUALITY = 85
DEFAULT_PROMPT = (
    "This is one page of an engineering drawing. In <=200 words, list:\n"
    "1. Drawing number and title (verbatim from titleblock)\n"
    "2. Sheet size (A0/A1/A3 if visible)\n"
    "3. Discipline (structural / civil / services)\n"
    "4. Up to 5 dimensions visible on the drawing (value in mm + what they measure)\n"
    "5. Up to 5 materials called out (verbatim labels)\n"
    "Reply only with the extracted facts; no preamble."
)


def render_page(pdf_path: Path, page: int, dpi: int) -> tuple[bytes, str]:
    """Render a PDF page, downscale to <=MAX_EDGE_PX, return (jpeg_bytes, media_type)."""
    poppler_path = os.getenv("POPPLER_PATH") or None
    images = convert_from_path(
        str(pdf_path),
        dpi=dpi,
        first_page=page,
        last_page=page,
        fmt="png",
        poppler_path=poppler_path,
    )
    if not images:
        raise RuntimeError(f"pdf2image returned no images for {pdf_path} page {page}")
    img = images[0]
    longest = max(img.size)
    if longest > MAX_EDGE_PX:
        scale = MAX_EDGE_PX / longest
        new_size = (int(img.size[0] * scale), int(img.size[1] * scale))
        img = img.resize(new_size, Image.LANCZOS)
    if img.mode != "RGB":
        img = img.convert("RGB")
    buf = io.BytesIO()
    img.save(buf, format="JPEG", quality=JPEG_QUALITY, optimize=True)
    return buf.getvalue(), "image/jpeg"


def call_vision(img_bytes: bytes, media_type: str, prompt: str, model: str) -> str:
    client = Anthropic()
    encoded = base64.standard_b64encode(img_bytes).decode("ascii")
    msg = client.messages.create(
        model=model,
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "media_type": media_type,
                            "data": encoded,
                        },
                    },
                    {"type": "text", "text": prompt},
                ],
            }
        ],
    )
    return "".join(block.text for block in msg.content if block.type == "text")


def main() -> int:
    load_dotenv()
    if not os.getenv("ANTHROPIC_API_KEY"):
        print("ERROR: ANTHROPIC_API_KEY not set", file=sys.stderr)
        return 2

    parser = argparse.ArgumentParser(description="PDF → Claude Vision smoke test")
    parser.add_argument("pdf", type=Path, help="Path to PDF")
    parser.add_argument("--page", type=int, default=1, help="1-indexed page number")
    parser.add_argument("--dpi", type=int, default=DEFAULT_DPI)
    parser.add_argument("--prompt", default=DEFAULT_PROMPT)
    parser.add_argument("--model", default=DEFAULT_MODEL)
    parser.add_argument("--save-png", type=Path, help="Optional: write rendered PNG to this path")
    args = parser.parse_args()

    if not args.pdf.exists():
        print(f"ERROR: PDF not found: {args.pdf}", file=sys.stderr)
        return 2

    print(f"Rendering {args.pdf.name} page {args.page} @ {args.dpi} DPI...", file=sys.stderr)
    img_bytes, media_type = render_page(args.pdf, args.page, args.dpi)
    print(f"  -> {len(img_bytes) / 1024:.1f} KB {media_type}", file=sys.stderr)

    if args.save_png:
        args.save_png.write_bytes(img_bytes)
        print(f"  -> saved {args.save_png}", file=sys.stderr)

    print(f"Calling {args.model}...", file=sys.stderr)
    response = call_vision(img_bytes, media_type, args.prompt, args.model)
    print(response)
    return 0


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