import math

from flyway.domain.errors import BusinessError


def parse_units(text: str | None) -> list[int]:
    units = []
    for part in (text or "").replace(";", ",").split(","):
        part = part.strip()
        if not part:
            continue
        if not part.isdigit() or int(part) < 1:
            raise BusinessError(f'Invalid unit "{part}".', "available_unit")
        units.append(int(part))
    return units


def validate_units(default_unit: int, available_unit: str | None) -> None:
    """文档 10.1-2：可用单位加上默认单位后，都必须是其中最小单位的整数倍。"""
    if default_unit < 1:
        raise BusinessError("Default unit must be at least 1.", "default_unit")
    units = sorted(set(parse_units(available_unit)) | {default_unit})
    base = units[0]
    bad = [u for u in units[1:] if u % base]
    if bad:
        raise BusinessError(
            f'The value "{",".join(map(str, bad))}" for "Available unit" is not a multiple of {base}.',
            "available_unit",
        )


def merge_quantity(q1: int, u1: int, q2: int, u2: int) -> tuple[int, int]:
    """文档 10.1-3：同产品同批号合并，取较小单位按总量换算。"""
    total = q1 * u1 + q2 * u2
    unit = min(u1, u2)
    if total % unit:  # 旧系统在此整除截断会丢库存；改用最大公约数，总量不变
        unit = math.gcd(u1, u2)
    return total // unit, unit


def pick_unit_for_remaining(remaining: int, default_unit: int, available: list[int]) -> tuple[int, int, int] | None:
    """文档 10.4-2“一键带出剩余”的旧算法；第三个值是被遗漏的余数（10.4-3 待业务确认是否修正）。"""
    if remaining < 1:
        return None
    unit = default_unit
    if unit < 1 or remaining % unit:
        unit = next((u for u in sorted(available, reverse=True) if remaining % u == 0), 0)
        if unit < 1:
            unit = next((u for u in available if remaining >= u), 0)
    if unit < 1:
        return None
    return remaining // unit, unit, remaining % unit
