"""Normalize MJ-RC5 scanner pages without changing OMR recognition rules."""

from __future__ import annotations

from pathlib import Path

from PIL import Image, ImageOps


LETTER_RATIO = 11 / 8.5


def _scanner_form(image: Image.Image) -> Image.Image:
    """Return the half-sheet form area from a full- or half-letter scan."""
    width, height = image.size
    ratio = height / width
    # Production full-letter scans place one half-sheet in the top half.
    if 1.15 <= ratio <= 1.45:
        return image.crop((0, 0, width, height // 2))
    return image.copy()


def _pad_form(form: Image.Image) -> Image.Image:
    """Place a landscape form at the top of the portrait canvas RC5 expects."""
    target_height = max(form.height, round(form.width * LETTER_RATIO))
    canvas = Image.new("L", (form.width, target_height), 255)
    canvas.paste(form, (0, 0))
    return canvas


def normalize_scanner_page(source: Path, destination: Path, angle: int = 0) -> None:
    """Crop, orient, and pad a scanner page while preserving its pixels."""
    with Image.open(source) as opened:
        image = ImageOps.exif_transpose(opened).convert("L")
        form = _scanner_form(image)
        if angle:
            form = form.rotate(angle, expand=True, fillcolor=255)
        normalized = _pad_form(form)
        destination.parent.mkdir(parents=True, exist_ok=True)
        normalized.save(destination, format="PNG")


def normalize_phone_image(source: Path, destination: Path, angle: int = 0) -> None:
    """Apply EXIF orientation and an optional retry rotation to a phone image."""
    with Image.open(source) as opened:
        image = ImageOps.exif_transpose(opened).convert("L")
        if angle:
            image = image.rotate(angle, expand=True, fillcolor=255)
        # Sideways captures become landscape after rotation. Padding below the
        # form gives marker detection the same portrait geometry as a scan.
        if image.width > image.height:
            image = _pad_form(image)
        destination.parent.mkdir(parents=True, exist_ok=True)
        image.save(destination, format="PNG")
