"""
mood_engine.py — Pure-function mood computation for the saltybot personality system.

No ROS2 imports — safe to unit-test without a live ROS2 environment.

Public API
----------
    compute_mood(soul, score, interaction_count, recent_events) -> str
    get_relationship_tier(soul, interaction_count) -> str
    build_greeting(soul, tier, mood, person_id) -> str

Mood semantics
--------------
    happy    : positive valence, comfortable familiarity
    playful  : high-energy, humorous (requires humor_level >= 7)
    curious  : low familiarity or novel person — inquisitive
    annoyed  : recent negative events or very low score

Tier semantics
--------------
    stranger  : interaction_count < threshold_regular
    regular   : threshold_regular <= count < threshold_favorite
    favorite  : count >= threshold_favorite
"""

from __future__ import annotations

# ── Mood / tier constants ──────────────────────────────────────────────────────

MOOD_HAPPY    = "happy"
MOOD_PLAYFUL  = "playful"
MOOD_CURIOUS  = "curious"
MOOD_ANNOYED  = "annoyed"

TIER_STRANGER  = "stranger"
TIER_REGULAR   = "regular"
TIER_FAVORITE  = "favorite"

# ── Event type constants (used by relationship_db and the node) ────────────────

EVENT_GREETING          = "greeting"
EVENT_POSITIVE          = "positive"
EVENT_NEGATIVE          = "negative"
EVENT_DETECTION         = "detection"

# How far back (seconds) to consider "recent" for mood computation
_RECENT_WINDOW_S = 120.0


# ── Mood computation ──────────────────────────────────────────────────────────

def compute_mood(
    soul: dict,
    score: float,
    interaction_count: int,
    recent_events: list,
) -> str:
    """Compute the current mood for a given person.

    Parameters
    ----------
    soul : dict
        Parsed SOUL.md configuration.
    score : float
        Relationship score for the current person (higher = more familiar).
    interaction_count : int
        Total number of times we have seen this person.
    recent_events : list of dict
        Each dict: ``{"type": str, "dt": float}`` where ``dt`` is seconds ago.
        Only events with ``dt < 120.0`` are considered "recent".

    Returns
    -------
    str
        One of: ``"happy"``, ``"playful"``, ``"curious"``, ``"annoyed"``.
    """
    base_mood    = soul.get("base_mood", MOOD_PLAYFUL)
    humor_level  = float(soul.get("humor_level", 5))

    # Count recent negative/positive events
    recent_neg = sum(
        1 for e in recent_events
        if e.get("type") == EVENT_NEGATIVE and e.get("dt", 1e9) < _RECENT_WINDOW_S
    )
    recent_pos = sum(
        1 for e in recent_events
        if e.get("type") in (EVENT_POSITIVE, EVENT_GREETING)
        and e.get("dt", 1e9) < _RECENT_WINDOW_S
    )

    # Hard override: multiple negatives → annoyed
    if recent_neg >= 2:
        return MOOD_ANNOYED

    # No prior interactions or brand-new person → curious
    if interaction_count == 0 or score < 1.0:
        return MOOD_CURIOUS

    # Stranger tier (low count) → curious
    threshold_regular = int(soul.get("threshold_regular", 5))
    if interaction_count < threshold_regular:
        return MOOD_CURIOUS

    # Familiar person: check positive events and humor level
    if recent_pos >= 1 or score >= 20.0:
        if humor_level >= 7:
            return MOOD_PLAYFUL
        return MOOD_HAPPY

    # High score / favorite
    threshold_fav = int(soul.get("threshold_favorite", 20))
    if interaction_count >= threshold_fav:
        if humor_level >= 7:
            return MOOD_PLAYFUL
        return MOOD_HAPPY

    return base_mood


# ── Tier classification ────────────────────────────────────────────────────────

def get_relationship_tier(soul: dict, interaction_count: int) -> str:
    """Return the relationship tier string for a given interaction count.

    Parameters
    ----------
    soul : dict
        Parsed SOUL.md configuration.
    interaction_count : int
        Total number of times we have seen this person.

    Returns
    -------
    str
        One of: ``"stranger"``, ``"regular"``, ``"favorite"``.
    """
    threshold_regular  = int(soul.get("threshold_regular",  5))
    threshold_favorite = int(soul.get("threshold_favorite", 20))
    if interaction_count >= threshold_favorite:
        return TIER_FAVORITE
    if interaction_count >= threshold_regular:
        return TIER_REGULAR
    return TIER_STRANGER


# ── Greeting builder ──────────────────────────────────────────────────────────

def build_greeting(soul: dict, tier: str, mood: str, person_id: str = "") -> str:
    """Compose a greeting string for a person.

    Parameters
    ----------
    soul : dict
        Parsed SOUL.md configuration.
    tier : str
        Relationship tier (``"stranger"``, ``"regular"``, ``"favorite"``).
    mood : str
        Current mood (used to prefix the greeting).
    person_id : str
        Person identifier / display name.  Substituted for ``{name}``
        in the template.

    Returns
    -------
    str
        A complete, ready-to-display greeting string.
    """
    template_key = {
        TIER_STRANGER: "greeting_stranger",
        TIER_REGULAR:  "greeting_regular",
        TIER_FAVORITE: "greeting_favorite",
    }.get(tier, "greeting_stranger")

    template = soul.get(template_key, "Hello!")
    base_greeting = template.replace("{name}", person_id or "friend")

    prefix_key = f"mood_prefix_{mood}"
    prefix = soul.get(prefix_key, "")

    if prefix:
        # Avoid double punctuation / duplicate capital letters
        base_first = base_greeting[0].lower() if base_greeting else ""
        greeting = f"{prefix}{base_first}{base_greeting[1:]}"
    else:
        greeting = base_greeting

    return greeting
