"""Crop primitive — vendored from backend/app/services/ml/crops.py so the agent
is self-contained. Keep in sync if the floor logic changes."""
from PIL import Image

MIN_CROP_FRACTION = 0.10
MIN_CROP_PX = 64


def crop_region(
    img: Image.Image,
    bbox: tuple[float, float, float, float],
    *,
    pad: float = 0.0,
    min_fraction: float = MIN_CROP_FRACTION,
    min_px: int = MIN_CROP_PX,
) -> Image.Image | None:
    """Crop a NORMALIZED bbox (x, y, w, h in [0,1]); None if below the size
    floor (max of a fraction-of-short-side and an absolute pixel floor)."""
    iw, ih = img.size
    x, y, w, h = bbox
    px, py, pw, ph = x * iw, y * ih, w * iw, h * ih
    if pad:
        px -= pw * pad / 2.0
        py -= ph * pad / 2.0
        pw *= (1.0 + pad)
        ph *= (1.0 + pad)
    left = max(0, int(round(px)))
    top = max(0, int(round(py)))
    right = min(iw, int(round(px + pw)))
    bottom = min(ih, int(round(py + ph)))
    if right <= left or bottom <= top:
        return None
    floor = max(min_px, int(min_fraction * min(iw, ih)))
    if min(right - left, bottom - top) < floor:
        return None
    return img.crop((left, top, right, bottom)).convert("RGB")
