"""Time adapter — circadian awareness for Timmy.

Emits time-of-day events so Timmy knows the current period
and tracks how long since the last user interaction.
"""

import logging
from datetime import UTC, datetime

from infrastructure.events.bus import emit

logger = logging.getLogger(__name__)

# Time-of-day periods: (event_name, start_hour, end_hour)
_PERIODS = [
    ("morning", 6, 9),
    ("afternoon", 12, 14),
    ("evening", 18, 20),
    ("late_night", 23, 24),
    ("late_night", 0, 3),
]


def classify_period(hour: int) -> str | None:
    """Return the circadian period name for a given hour, or None."""
    for name, start, end in _PERIODS:
        if start <= hour < end:
            return name
    return None


class TimeAdapter:
    """Emits circadian and interaction-tracking events."""

    def __init__(self) -> None:
        self._last_interaction: datetime | None = None
        self._last_period: str | None = None
        self._last_date: str | None = None

    def record_interaction(self, now: datetime | None = None) -> None:
        """Record a user interaction timestamp."""
        self._last_interaction = now or datetime.now(UTC)

    def time_since_last_interaction(
        self,
        now: datetime | None = None,
    ) -> float | None:
        """Seconds since last user interaction, or None if no interaction."""
        if self._last_interaction is None:
            return None
        current = now or datetime.now(UTC)
        return (current - self._last_interaction).total_seconds()

    async def tick(self, now: datetime | None = None) -> list[str]:
        """Check current time and emit relevant events.

        Returns list of event types emitted (useful for testing).
        """
        current = now or datetime.now(UTC)
        emitted: list[str] = []

        # --- new_day ---
        date_str = current.strftime("%Y-%m-%d")
        if self._last_date is not None and date_str != self._last_date:
            event_type = "time.new_day"
            await emit(event_type, source="time_adapter", data={"date": date_str})
            emitted.append(event_type)
        self._last_date = date_str

        # --- circadian period ---
        period = classify_period(current.hour)
        if period is not None and period != self._last_period:
            event_type = f"time.{period}"
            await emit(
                event_type,
                source="time_adapter",
                data={"hour": current.hour, "period": period},
            )
            emitted.append(event_type)
            self._last_period = period

        return emitted
