"""Combat encounter management and processing."""

import time

from mudlib.combat.encounter import IDLE_TIMEOUT, CombatEncounter, CombatState
from mudlib.combat.stamina import check_stamina_cues
from mudlib.entity import Entity
from mudlib.gmcp import send_char_status, send_char_vitals
from mudlib.render.colors import colorize
from mudlib.render.pov import render_pov

# Global list of active combat encounters
active_encounters: list[CombatEncounter] = []


def start_encounter(attacker: Entity, defender: Entity) -> CombatEncounter:
    """Start a new combat encounter.

    Args:
        attacker: The entity initiating combat
        defender: The target entity

    Returns:
        The created CombatEncounter

    Raises:
        ValueError: If either entity is already in combat
    """
    # Check if either entity is already in combat
    if get_encounter(attacker) is not None:
        msg = f"{attacker.name} is already in combat"
        raise ValueError(msg)

    if get_encounter(defender) is not None:
        msg = f"{defender.name} is already in combat"
        raise ValueError(msg)

    # Create and register the encounter
    encounter = CombatEncounter(
        attacker=attacker,
        defender=defender,
        last_action_at=time.monotonic(),
    )
    active_encounters.append(encounter)

    # Cancel any active power-up tasks
    for entity in (attacker, defender):
        task = getattr(entity, "_power_task", None)
        if task is not None:
            task.cancel()
            if hasattr(entity, "_power_task"):
                entity._power_task = None  # type: ignore[attr-defined]

    return encounter


def get_encounter(entity: Entity) -> CombatEncounter | None:
    """Find the active encounter for an entity.

    Args:
        entity: The entity to search for

    Returns:
        CombatEncounter if entity is in combat, None otherwise
    """
    for encounter in active_encounters:
        if encounter.attacker is entity or encounter.defender is entity:
            return encounter
    return None


def end_encounter(encounter: CombatEncounter) -> None:
    """End and remove an encounter from the active list.

    Args:
        encounter: The encounter to end
    """
    if encounter in active_encounters:
        active_encounters.remove(encounter)


async def process_combat() -> None:
    """Process all active combat encounters.

    This should be called each game loop tick to advance combat state machines.
    """
    from mudlib.player import Player

    now = time.monotonic()

    for encounter in active_encounters[:]:  # Copy list to allow modification
        # Check for no-damage timeout.
        if now - encounter.last_action_at > IDLE_TIMEOUT:
            await encounter.attacker.send("Combat has fizzled out.\r\n")
            await encounter.defender.send("Combat has fizzled out.\r\n")

            for entity in (encounter.attacker, encounter.defender):
                if isinstance(entity, Player) and entity.mode == "combat":
                    entity.mode_stack.pop()
                    send_char_status(entity)

            end_encounter(encounter)
            continue

        # Save previous state to detect transitions
        previous_state = encounter.state

        # Tick the state machine
        encounter.tick(now)

        # Send announce message on PENDING → RESOLVE transition
        if (
            previous_state == CombatState.PENDING
            and encounter.state == CombatState.RESOLVE
            and encounter.current_move
            and encounter.current_move.announce
        ):
            template = encounter.current_move.announce
            announce_color = encounter.current_move.announce_color

            for viewer in (encounter.attacker, encounter.defender):
                msg = render_pov(
                    template, viewer, encounter.attacker, encounter.defender
                )
                if announce_color:
                    color_depth = getattr(viewer, "color_depth", None)
                    msg = colorize(f"{{{announce_color}}}{msg}{{/}}", color_depth)
                await viewer.send(msg + "\r\n")

        # Auto-resolve if in RESOLVE state
        if encounter.state == CombatState.RESOLVE:
            # Save current_move before resolve() clears it
            current_move = encounter.current_move
            result = encounter.resolve()

            # Send resolution messages to both participants using POV
            resolve_color = current_move.resolve_color if current_move else "bold"

            for viewer in (encounter.attacker, encounter.defender):
                msg = render_pov(
                    result.resolve_template,
                    viewer,
                    encounter.attacker,
                    encounter.defender,
                )
                if resolve_color:
                    color_depth = getattr(viewer, "color_depth", None)
                    msg = colorize(f"{{{resolve_color}}}{msg}{{/}}", color_depth)
                await viewer.send(msg + "\r\n")

            # Send vitals update after damage resolution
            for entity in (encounter.attacker, encounter.defender):
                if isinstance(entity, Player):
                    send_char_vitals(entity)

            # Check stamina cues after damage
            await check_stamina_cues(encounter.attacker)
            await check_stamina_cues(encounter.defender)
