"""Parse timeout duration strings.

Pure parsing logic: convert strings like '10m', '2h', '30s' to seconds.
No I/O imports.

This module provides duration parsing for JobSpec.timeout field
per docs/INTERFACES.md Section A.

Supported formats:
    - <number>s: seconds (e.g., '30s', '45 seconds')
    - <number>m: minutes (e.g., '10m', '5 minutes')
    - <number>h: hours (e.g., '2h', '1 hour')

All durations are converted to integer seconds.
"""

from deal import post, pre, raises


@pre(lambda s: s is not None)
@pre(lambda s: len(s) > 0)
@post(lambda result: result >= 0)
@raises(ValueError)
def parse_timeout(s: str) -> int:
    """Parse a duration string into seconds.

    Supports formats:
        - '30s' -> 30 seconds
        - '10m' -> 600 seconds (10 minutes)
        - '2h' -> 7200 seconds (2 hours)
        - '30' -> 30 seconds (bare number)

    Whitespace is ignored. Format is case-insensitive.

    Args:
        s: Duration string (e.g., '10m', '2h', '30s').

    Returns:
        Duration in seconds as a non-negative integer.

    Raises:
        ValueError: If the string format is invalid.

    Doctests:
        >>> parse_timeout('30s')
        30
        >>> parse_timeout('10m')
        600
        >>> parse_timeout('2h')
        7200
        >>> parse_timeout('30')
        30

        >>> # Case insensitive
        >>> parse_timeout('10M')
        600
        >>> parse_timeout('2H')
        7200

        >>> # Whitespace handling
        >>> parse_timeout(' 10m ')
        600
        >>> parse_timeout(' 30 s ')
        30

        >>> # Zero values
        >>> parse_timeout('0s')
        0
        >>> parse_timeout('0m')
        0
        >>> parse_timeout('0h')
        0
        >>> parse_timeout('0')
        0

        >>> # Large values
        >>> parse_timeout('90m')
        5400
        >>> parse_timeout('24h')
        86400
        >>> parse_timeout('1000s')
        1000
    """
    # Strip whitespace and convert to lowercase
    s = s.strip().lower()

    # Handle bare number (assume seconds)
    if s.isdigit():
        return int(s)

    # Extract numeric part and unit
    i = 0
    while i < len(s) and (s[i].isdigit() or s[i] == "."):
        i += 1

    if i == 0:
        raise ValueError(f"Invalid timeout format: no number found in '{s}'")

    number_str = s[:i]
    unit = s[i:].strip()

    # Parse the number
    try:
        if "." in number_str:
            # Handle floating point, convert to int seconds
            number = float(number_str)
        else:
            number = int(number_str)
    except ValueError:
        raise ValueError(f"Invalid timeout format: invalid number '{number_str}'")

    # Convert based on unit
    if unit == "s" or unit == "seconds" or unit == "second":
        return int(number)
    elif unit == "m" or unit == "minutes" or unit == "minute":
        return int(number * 60)
    elif unit == "h" or unit == "hours" or unit == "hour":
        return int(number * 3600)
    else:
        raise ValueError(f"Invalid timeout unit: '{unit}'. Use 's', 'm', or 'h'")
