from dataclasses import dataclass


@dataclass
class AbsoluteBoxValues:
    top: int
    right: int
    bottom: int
    left: int


@dataclass
class BoxValues:
    top: int | str
    right: int | str
    bottom: int | str
    left: int | str

    def normalize_to_dimensions(self, width, height) -> AbsoluteBoxValues:
        parts = []
        dimension_base = [height, width, height, width]
        for index, part in enumerate([self.top, self.right, self.bottom, self.left]):
            if isinstance(part, str) and part.endswith("%"):
                parts.append(int(int(part.strip("%")) / 100 * dimension_base[index]))
            else:
                # simple integer value
                parts.append(int(part))
        return AbsoluteBoxValues(*parts)


class BoxValueError(ValueError):
    pass


def parse_box_value(value, delimiter=","):
    """
    Parse CSS-style padding values into a dictionary.

    Accepts formats:
    - Single value (all sides)
    - Two values (vertical | horizontal)
    - Three values (top | horizontal | bottom)
    - Four values (top | right | bottom | left)

    Args:
        value: A string containing CSS-style box values

    Returns:
        BoxValues dataclass with 'top', 'right', 'bottom', and 'left' attributes
    """
    parts = []
    for part_value in value.strip().split(delimiter):
        try:
            part = int(part_value.strip())
            parts.append(part)
        except ValueError:  # noqa: PERF203
            # not an int - is it a %?
            if (part_value := part_value.strip()).endswith("%"):
                parts.append(part_value)
            else:
                raise BoxValueError(f"Invalid padding value: {part_value}")

    if len(parts) == 1:
        # If only one value is provided, apply to all sides
        return BoxValues(top=parts[0], right=parts[0], bottom=parts[0], left=parts[0])
    elif len(parts) == 2:
        # If two values: first is top/bottom, second is left/right
        return BoxValues(top=parts[0], right=parts[1], bottom=parts[0], left=parts[1])
    elif len(parts) == 3:
        # If three values: top, left/right, bottom
        return BoxValues(top=parts[0], right=parts[1], bottom=parts[2], left=parts[1])
    elif len(parts) == 4:
        # If four values: top, right, bottom, left
        return BoxValues(top=parts[0], right=parts[1], bottom=parts[2], left=parts[3])
    else:
        raise BoxValueError(
            "Invalid outpaint padding box value format: {value} "
            "Expected: 1 (all-sides), 2 (top/bottom, left/right) "
            "or 4 (top, right, bottom, left)values of int or percentages. e.g. 10px, 20%"
        )
