"""L6 EMOTIONAL Layer

Map by frequency and sentiment.
"""
from __future__ import annotations

from typing import List, Optional

from .base import Layer, LayerID, Token
from .._core import PRIME_131


class L6_Emotional(Layer):
    """L6 EMOTIONAL: Map by frequency and sentiment."""

    LAYER_ID = LayerID.EMOTIONAL
    LAYER_NAME = "EMOTIONAL"
    LAYER_DESCRIPTION = "Map by frequency and sentiment"

    # 154 emotions mapped to basins
    EMOTIONS = {
        "calm": (0, 10),
        "focused": (11, 25),
        "curious": (26, 40),
        "excited": (41, 55),
        "confident": (56, 70),
        "joyful": (71, 85),
        "intense": (86, 100),
        "urgent": (101, 115),
        "critical": (116, 130),
    }

    def query(self, pattern: str, limit: int = 100) -> List[Token]:
        """Query by emotional state."""
        pattern = pattern.lower()
        if pattern in self.EMOTIONS:
            min_basin, max_basin = self.EMOTIONS[pattern]
            return [t for t in self._memory._tokens.values()
                    if min_basin <= t.basin <= max_basin][:limit]
        return []

    def filter(self, tokens: List[Token], **criteria) -> List[Token]:
        """Filter by emotional criteria."""
        results = tokens

        if "emotion" in criteria:
            emotion = criteria["emotion"].lower()
            if emotion in self.EMOTIONS:
                min_b, max_b = self.EMOTIONS[emotion]
                results = [t for t in results if min_b <= t.basin <= max_b]

        if "min_energy" in criteria:
            min_e = criteria["min_energy"]
            results = [t for t in results if t.energy >= min_e]

        if "min_coherence" in criteria:
            min_c = criteria["min_coherence"]
            results = [t for t in results if t.coherence >= min_c]

        return results

    def navigate(self, token: Token, direction: str) -> Optional[Token]:
        """Navigate by emotional direction."""
        if direction == "calmer":
            candidates = [t for t in self._memory._tokens.values()
                         if t.basin < token.basin]
            return min(candidates, key=lambda t: t.basin) if candidates else None
        elif direction == "more_intense":
            candidates = [t for t in self._memory._tokens.values()
                         if t.basin > token.basin]
            return min(candidates, key=lambda t: t.basin) if candidates else None
        return None

    def distance(self, a: Token, b: Token) -> float:
        """Emotional distance: energy and coherence difference."""
        energy_diff = abs(a.energy - b.energy) / 100
        coherence_diff = abs(a.coherence - b.coherence)
        return energy_diff + coherence_diff

    def emotional_state(self, token: Token) -> str:
        """Get emotional state name for token."""
        for emotion, (min_b, max_b) in self.EMOTIONS.items():
            if min_b <= token.basin <= max_b:
                return emotion
        return "neutral"

    def coherence_score(self, token: Token) -> float:
        """Get coherence score for token."""
        return token.coherence
