"""Zone definitions and pace / speed conversion utilities."""

from __future__ import annotations

from pace2fit.model import PaceTarget, ZoneTarget, Target


# ---------------------------------------------------------------------------
# Pace  <->  Speed helpers
# ---------------------------------------------------------------------------


def pace_to_speed(minutes: int, seconds: int = 0) -> float:
    """Convert a pace (min:sec per km) to speed in m/s.

    Examples:
        >>> pace_to_speed(5, 0)   # 5:00/km
        3.3333333333333335
        >>> pace_to_speed(6, 0)   # 6:00/km
        2.7777777777777777
    """
    total_seconds = minutes * 60 + seconds
    if total_seconds <= 0:
        raise ValueError(f"Pace must be positive, got {minutes}:{seconds:02d}")
    return 1000.0 / total_seconds


def speed_to_pace(speed: float) -> tuple[int, int]:
    """Convert speed in m/s back to pace as (minutes, seconds) per km.

    Returns integer minutes and seconds (rounded).
    """
    if speed <= 0:
        raise ValueError(f"Speed must be positive, got {speed}")
    total_seconds = round(1000.0 / speed)
    return divmod(total_seconds, 60)


def pace_str_to_speed(pace_str: str) -> float:
    """Parse a pace string like ``"5:30"`` and return speed in m/s."""
    parts = pace_str.split(":")
    if len(parts) != 2:
        raise ValueError(f"Invalid pace format '{pace_str}', expected MM:SS")
    minutes, seconds = int(parts[0]), int(parts[1])
    return pace_to_speed(minutes, seconds)


# ---------------------------------------------------------------------------
# Named zone definitions
# ---------------------------------------------------------------------------

# Named zones that map to pace ranges (min/km).
# Format: { name: (slow_pace, fast_pace) } where each pace is "M:SS".
NAMED_PACE_ZONES: dict[str, tuple[str, str]] = {
    "easy": ("6:30", "6:00"),
    "recovery": ("7:00", "6:30"),
    "tempo": ("5:15", "5:00"),
    "threshold": ("4:45", "4:30"),
    "marathon": ("5:20", "5:00"),
    "hm": ("4:55", "4:40"),  # half-marathon
    "interval": ("4:15", "3:45"),
    "repetition": ("3:45", "3:30"),
}


def resolve_named_zone(name: str) -> Target:
    """Resolve a zone name to a *Target*.

    - ``"Z1"`` .. ``"Z5"`` -> :class:`ZoneTarget`
    - Named paces (``"easy"``, ``"threshold"``, etc.) -> :class:`PaceTarget`

    Raises :class:`ValueError` for unknown zone names.
    """
    lower = name.lower()

    # Heart-rate zones: Z1 .. Z5
    if lower.startswith("z") and len(lower) == 2 and lower[1].isdigit():
        zone_num = int(lower[1])
        if not 1 <= zone_num <= 5:
            raise ValueError(f"HR zone must be Z1-Z5, got {name}")
        return ZoneTarget(zone=zone_num)

    # Named pace zones
    if lower in NAMED_PACE_ZONES:
        slow, fast = NAMED_PACE_ZONES[lower]
        return PaceTarget(low=pace_str_to_speed(slow), high=pace_str_to_speed(fast))

    raise ValueError(
        f"Unknown zone '{name}'. "
        f"Valid zones: Z1-Z5, {', '.join(sorted(NAMED_PACE_ZONES))}"
    )
