"""
ARIA Betriebsmodi — steuern wann und wie ARIA spricht.

Jeder Modus definiert, ob ARIA Audio ausgeben darf,
ob sie proaktiv sprechen darf und ob Unterbrechungen erlaubt sind.
"""

from __future__ import annotations

import logging
from dataclasses import dataclass
from enum import Enum
from typing import Optional

logger = logging.getLogger(__name__)


@dataclass(frozen=True)
class ModeConfig:
    """Konfiguration eines Betriebsmodus."""

    name: str
    emoji: str
    activation_phrase: str
    can_speak: bool
    can_interrupt: bool
    audio_output: bool
    proactive: bool


class Mode(Enum):
    """ARIAs Betriebsmodi mit zugehoeriger Konfiguration."""

    NORMAL = ModeConfig(
        name="Normal",
        emoji="\U0001f7e2",  # Gruener Kreis
        activation_phrase="ARIA, Normal-Modus",
        can_speak=True,
        can_interrupt=True,
        audio_output=True,
        proactive=True,
    )

    DND = ModeConfig(
        name="Nicht stoeren",
        emoji="\U0001f534",  # Roter Kreis
        activation_phrase="ARIA, nicht stoeren",
        can_speak=False,
        can_interrupt=False,
        audio_output=False,
        proactive=False,
    )

    WHISPER = ModeConfig(
        name="Fluester",
        emoji="\U0001f7e1",  # Gelber Kreis
        activation_phrase="ARIA, leise bitte",
        can_speak=False,
        can_interrupt=False,
        audio_output=False,
        proactive=True,
    )

    HANGAR = ModeConfig(
        name="Hangar",
        emoji="\u2708\ufe0f",  # Flugzeug
        activation_phrase="ARIA, ich arbeite",
        can_speak=True,
        can_interrupt=False,
        audio_output=True,
        proactive=False,
    )

    GAMING = ModeConfig(
        name="Gaming",
        emoji="\U0001f3ae",  # Gamepad
        activation_phrase="ARIA, Gaming-Modus",
        can_speak=True,
        can_interrupt=False,
        audio_output=True,
        proactive=False,
    )

    @property
    def config(self) -> ModeConfig:
        return self.value


# Aktivierungsphrasen auf Modi mappen (lowercase fuer Vergleich)
_ACTIVATION_MAP: dict[str, Mode] = {
    mode.config.activation_phrase.lower(): mode for mode in Mode
}

# ID-Mapping fuer API-Mode-Wechsel (z.B. App ModeSelector schickt 'normal')
_ID_MAP: dict[str, Mode] = {
    "normal": Mode.NORMAL,
    "nicht_stoeren": Mode.DND,
    "dnd": Mode.DND,
    "fluester": Mode.WHISPER,
    "whisper": Mode.WHISPER,
    "hangar": Mode.HANGAR,
    "gaming": Mode.GAMING,
}


def mode_from_id(mode_id: str) -> Optional[Mode]:
    """ID-basiertes Mapping fuer API-Mode-Wechsel (ohne Aktivierungsphrase)."""
    if not mode_id:
        return None
    return _ID_MAP.get(mode_id.strip().lower())


# Kanonische IDs fuer Broadcasts (matchen die App-UI-IDs in ModeSelector)
_CANONICAL_ID: dict[Mode, str] = {
    Mode.NORMAL: "normal",
    Mode.DND: "nicht_stoeren",
    Mode.WHISPER: "fluester",
    Mode.HANGAR: "hangar",
    Mode.GAMING: "gaming",
}


def canonical_id(mode: Mode) -> str:
    """Kanonische ID die App + Diagnostic + Bridge gleichermassen kennen."""
    return _CANONICAL_ID.get(mode, mode.name.lower())


def detect_mode_switch(text: str) -> Optional[Mode]:
    """Erkennt ob ein Text eine Modus-Umschaltung enthaelt.

    Vergleicht den Text (case-insensitive) mit den Aktivierungsphrasen
    aller Modi. Gibt den neuen Modus zurueck oder None.

    Args:
        text: Eingabetext vom Benutzer.

    Returns:
        Der erkannte Modus oder None wenn kein Wechsel erkannt wurde.
    """
    text_lower = text.strip().lower()

    for phrase, mode in _ACTIVATION_MAP.items():
        if phrase in text_lower:
            logger.info(
                "Modus-Wechsel erkannt: %s %s",
                mode.config.emoji,
                mode.config.name,
            )
            return mode

    return None


def should_speak(mode: Mode, is_critical: bool = False) -> bool:
    """Prueft ob eine Nachricht im aktuellen Modus gesprochen werden soll.

    Im DND-Modus wird nur bei kritischen Alarmen gesprochen.
    Alle anderen Modi respektieren ihre can_speak / audio_output Flags.

    Args:
        mode: Aktueller Betriebsmodus.
        is_critical: True wenn es sich um einen kritischen Alarm handelt.

    Returns:
        True wenn die Nachricht gesprochen werden soll.
    """
    # Kritische Alarme durchbrechen den DND-Modus
    if is_critical and mode == Mode.DND:
        logger.warning("Kritischer Alarm im DND-Modus — Sprachausgabe erzwungen")
        return True

    return mode.config.can_speak and mode.config.audio_output
