"""Aspect ratio parsing and validation utilities."""

__author__ = "Lene Preuss <lene.preuss@gmail.com>"

import re

from stable_delusion.exceptions.validation_error import ValidationError


def parse_aspect_ratio(s: str) -> tuple[int, int]:
    """
    Parse an aspect ratio string like '16:9' into (16, 9).

    Raises:
        ValidationError: if the format is not 'W:H' with positive integers.
    """
    match = re.fullmatch(r"(\d+):(\d+)", s.strip())
    if not match:
        raise ValidationError(
            f"Invalid aspect ratio format: '{s}'. Expected 'W:H', e.g. '16:9'.",
            field="aspect_ratio",
            value=s,
        )
    w, h = int(match.group(1)), int(match.group(2))
    if w <= 0 or h <= 0:
        raise ValidationError(
            f"Aspect ratio dimensions must be positive integers: '{s}'.",
            field="aspect_ratio",
            value=s,
        )
    return w, h


def validate_image_aspect_ratio(
    width: int, height: int, expected: str, tolerance: float = 0.02
) -> bool:
    """
    Return True if width/height matches expected ratio within a relative tolerance.

    Args:
        width: Image width in pixels.
        height: Image height in pixels.
        expected: Aspect ratio string, e.g. '16:9'.
        tolerance: Relative tolerance (default 0.02 = 2%).
    """
    exp_w, exp_h = parse_aspect_ratio(expected)
    actual_ratio = width / height
    expected_ratio = exp_w / exp_h
    return abs(actual_ratio - expected_ratio) <= tolerance * expected_ratio
