#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse
import json
import sys
import warnings
from pathlib import Path

warnings.filterwarnings("ignore")


def responder_error(mensaje: str, code: int = 1):
    print(json.dumps({
        "ok": False,
        "error": mensaje
    }, ensure_ascii=False))
    sys.exit(code)


try:
    import fitz  # PyMuPDF
except Exception as exc:
    responder_error(
        "No se pudo importar PyMuPDF. Instale con: py -m pip install pymupdf. "
        f"Detalle: {exc}"
    )


def guardar_pixmap(pix, salida: Path, formato: str = "png", jpg_quality: int = 92) -> None:
    formato = formato.lower().strip()

    if formato == "jpg" or formato == "jpeg":
        try:
            data = pix.tobytes("jpg", jpg_quality=jpg_quality)
        except TypeError:
            data = pix.tobytes("jpg")

        salida.write_bytes(data)
        return

    pix.save(str(salida))


def convertir_pdf_a_imagenes(
    pdf_path: Path,
    outdir: Path,
    dpi: int,
    formato: str = "png",
    jpg_quality: int = 92
) -> dict:
    if not pdf_path.exists():
        raise RuntimeError(f"No existe el PDF: {pdf_path}")

    if not pdf_path.is_file():
        raise RuntimeError(f"La ruta no es un archivo válido: {pdf_path}")

    if pdf_path.suffix.lower() != ".pdf":
        raise RuntimeError("El archivo seleccionado no es PDF.")

    if dpi <= 0:
        raise RuntimeError("El DPI debe ser mayor que cero.")

    formato = formato.lower().strip()

    if formato not in ["png", "jpg", "jpeg"]:
        raise RuntimeError("Formato no permitido. Use png o jpg.")

    if jpg_quality < 60 or jpg_quality > 100:
        raise RuntimeError("La calidad JPG debe estar entre 60 y 100.")

    outdir.mkdir(parents=True, exist_ok=True)

    doc = fitz.open(str(pdf_path))

    if doc.page_count <= 0:
        doc.close()
        raise RuntimeError("El PDF no tiene páginas.")

    pages = []
    zoom = dpi / 72.0
    matrix = fitz.Matrix(zoom, zoom)

    extension = "jpg" if formato in ["jpg", "jpeg"] else "png"

    try:
        for i in range(doc.page_count):
            page = doc.load_page(i)
            numero_pagina = i + 1

            # Renderiza la página completa.
            # colorspace=fitz.csRGB ayuda a mantener salida en color estable.
            pix = page.get_pixmap(
                matrix=matrix,
                colorspace=fitz.csRGB,
                alpha=False,
                annots=False
            )

            salida = outdir / f"page_{numero_pagina:04d}.{extension}"

            guardar_pixmap(
                pix=pix,
                salida=salida,
                formato=formato,
                jpg_quality=jpg_quality
            )

            pages.append({
                "page": numero_pagina,
                "image": str(salida),
                "method": "rendered_page",
                "format": extension,
                "width_px": int(pix.width),
                "height_px": int(pix.height),
                "dpi": int(dpi),
                "pdf_rotation": int(page.rotation),
                "pdf_width_pt": float(page.rect.width),
                "pdf_height_pt": float(page.rect.height)
            })

    finally:
        doc.close()

    return {
        "ok": True,
        "pdf": str(pdf_path),
        "outdir": str(outdir),
        "dpi": int(dpi),
        "format": extension,
        "total_pages": len(pages),
        "pages": pages
    }


def main():
    parser = argparse.ArgumentParser(
        description="Convierte PDF multipágina a imagen para procesamiento OMR."
    )

    parser.add_argument("--pdf", required=True, help="Ruta completa del PDF.")
    parser.add_argument("--outdir", required=True, help="Carpeta de salida para imágenes.")
    parser.add_argument("--dpi", type=int, default=240, help="Resolución. Recomendado: 220 a 250 para OMR.")
    parser.add_argument("--format", default="png", choices=["png", "jpg"], help="Formato de salida.")
    parser.add_argument("--jpg-quality", type=int, default=92, help="Calidad JPG si usa --format jpg.")

    args = parser.parse_args()

    try:
        pdf_path = Path(args.pdf)
        outdir = Path(args.outdir)

        resultado = convertir_pdf_a_imagenes(
            pdf_path=pdf_path,
            outdir=outdir,
            dpi=int(args.dpi),
            formato=str(args.format),
            jpg_quality=int(args.jpg_quality)
        )

        print(json.dumps(resultado, ensure_ascii=False))

    except Exception as exc:
        responder_error(str(exc))


if __name__ == "__main__":
    main()