"""NPC schedule system for time-based behavior transitions."""

from dataclasses import dataclass

from mudlib.entity import Mob
from mudlib.npc_behavior import transition_state


@dataclass
class ScheduleEntry:
    """A single schedule entry for a specific hour."""

    hour: int  # Game hour (0-23) when this entry activates
    state: str  # Behavior state to transition to
    location: dict | None = None  # Optional {"x": int, "y": int} to move to
    data: dict | None = None  # Optional behavior_data to set


@dataclass
class NpcSchedule:
    """Schedule for an NPC with multiple time-based entries."""

    entries: list[ScheduleEntry]

    def get_active_entry(self, hour: int) -> ScheduleEntry:
        """Get the schedule entry that should be active at the given hour.

        Returns the most recent entry at or before the given hour,
        wrapping around midnight if necessary.

        Args:
            hour: Game hour (0-23)

        Returns:
            The active ScheduleEntry for this hour
        """
        if not self.entries:
            raise ValueError("Schedule has no entries")

        # Find the most recent entry at or before this hour
        best_entry = None
        best_hour = -1

        for entry in self.entries:
            if entry.hour <= hour and entry.hour > best_hour:
                best_entry = entry
                best_hour = entry.hour

        # If no entry found before current hour, wrap around to last entry
        if best_entry is None:
            # Find the entry with the highest hour
            best_entry = max(self.entries, key=lambda e: e.hour)

        return best_entry


def process_schedules(mob_list: list[Mob], game_hour: int) -> None:
    """Process NPC schedules and apply transitions if hour has changed.

    Args:
        mob_list: List of mobs to process
        game_hour: Current game hour (0-23)
    """
    for mob in mob_list:
        if not mob.alive:
            continue

        # Skip mobs in conversation (don't interrupt active player interaction)
        if mob.behavior_state == "converse":
            continue

        schedule = mob.schedule
        if schedule is None or not isinstance(schedule, NpcSchedule):
            continue

        # Check if we've already processed this hour
        if mob.schedule_last_hour == game_hour:
            continue

        # Get the active entry for this hour
        entry = schedule.get_active_entry(game_hour)

        # Check if anything needs to change
        needs_state_change = mob.behavior_state != entry.state
        needs_location_change = entry.location is not None and (
            mob.x != entry.location["x"] or mob.y != entry.location["y"]
        )
        needs_data_change = entry.data is not None

        # Only apply changes if something actually changed
        if needs_state_change or needs_location_change or needs_data_change:
            # Transition state (this also sets behavior_data if entry.data is set)
            transition_state(mob, entry.state, entry.data)

            # Move mob if location specified
            if entry.location is not None:
                mob.x = entry.location["x"]
                mob.y = entry.location["y"]

        # Mark this hour as processed
        mob.schedule_last_hour = game_hour
