"""TimeRange — resolved, concrete time range with all fields populated."""

from datetime import UTC, datetime

from pydantic import BaseModel, ConfigDict


class TimeRange(BaseModel):
    """A resolved, concrete time range.

    All fields are populated after resolution from a TimeRangeSpec
    against dataset metadata or cache state.

    Attributes:
    sec : tuple[float, float]
        Start and end times in seconds ``(start, end)``.
    timestamp : tuple[int, int]
        Start and end times in samples ``(start_sample, end_sample)``.
    fs : float
        Sampling rate in Hz.
    dur_sec : float
        Duration in seconds.
    walltime_str : str
        Wall-clock time string (always UTC from backend).
    n : int
        Number of samples.
    """

    model_config = ConfigDict(frozen=True)

    sec: tuple[float, float]
    timestamp: tuple[int, int]
    fs: float
    dur_sec: float
    walltime_str: str
    n: int

    @property
    def walltime(self) -> datetime:
        """Parse walltime string to UTC-aware datetime.

        The backend always provides walltime in UTC.
        This property returns a timezone-aware datetime with UTC timezone.
        """
        return _parse_walltime_str(self.walltime_str)


def _parse_walltime_str(walltime: str) -> datetime:
    """Parse walltime string to UTC-aware datetime.

    The backend always provides walltime in UTC. This function ensures the
    returned datetime is always timezone-aware with UTC timezone.

    Args:
    walltime : str
        Wall-clock time string in UTC (from backend).

    Returns:
    datetime
        Timezone-aware datetime with UTC timezone.

    Raises:
    ValueError
        If the walltime string cannot be parsed.
    """
    try:
        # Try fromisoformat first (handles most ISO 8601 formats)
        dt = datetime.fromisoformat(walltime.replace("Z", "+00:00"))
        # Ensure timezone-aware (should already be from fromisoformat with +00:00)
        if dt.tzinfo is None:
            dt = dt.replace(tzinfo=UTC)
        return dt
    except ValueError:
        # Fallback to manual parsing for other formats
        for fmt in [
            "%Y-%m-%dT%H:%M:%S.%f",
            "%Y-%m-%dT%H:%M:%S",
            "%Y-%m-%d %H:%M:%S.%f",
            "%Y-%m-%d %H:%M:%S",
            "%a %b %d %H:%M:%S %Z %Y",  # "Tue Mar 17 12:37:14 UTC 2026"
        ]:
            try:
                dt = datetime.strptime(walltime, fmt)
                # strptime creates naive datetime - make it UTC-aware
                if dt.tzinfo is None:
                    dt = dt.replace(tzinfo=UTC)
                return dt
            except ValueError:
                continue
        raise ValueError(f"Unable to parse walltime: {walltime}") from None
