"""Tests for agent emotional state simulation (src/timmy/agents/emotional_state.py)."""

import time

from timmy.agents.emotional_state import (
    EMOTION_PROMPT_MODIFIERS,
    EMOTIONAL_STATES,
    EVENT_TRANSITIONS,
    EmotionalState,
    EmotionalStateTracker,
    _intensity_label,
)


class TestEmotionalState:
    """Test the EmotionalState dataclass."""

    def test_defaults(self):
        state = EmotionalState()
        assert state.current_emotion == "calm"
        assert state.intensity == 0.5
        assert state.previous_emotion == "calm"
        assert state.trigger_event == ""

    def test_to_dict_includes_label(self):
        state = EmotionalState(current_emotion="analytical")
        d = state.to_dict()
        assert d["emotion_label"] == "Analytical"
        assert d["current_emotion"] == "analytical"

    def test_to_dict_all_fields(self):
        state = EmotionalState(
            current_emotion="frustrated",
            intensity=0.8,
            previous_emotion="calm",
            trigger_event="task_failure",
        )
        d = state.to_dict()
        assert d["current_emotion"] == "frustrated"
        assert d["intensity"] == 0.8
        assert d["previous_emotion"] == "calm"
        assert d["trigger_event"] == "task_failure"


class TestEmotionalStates:
    """Validate the emotional states and transitions are well-defined."""

    def test_all_states_are_strings(self):
        for state in EMOTIONAL_STATES:
            assert isinstance(state, str)

    def test_all_states_have_prompt_modifiers(self):
        for state in EMOTIONAL_STATES:
            assert state in EMOTION_PROMPT_MODIFIERS

    def test_all_transitions_target_valid_states(self):
        for event_type, (emotion, intensity) in EVENT_TRANSITIONS.items():
            assert emotion in EMOTIONAL_STATES, f"{event_type} targets unknown state: {emotion}"
            assert 0.0 <= intensity <= 1.0, f"{event_type} has invalid intensity: {intensity}"


class TestEmotionalStateTracker:
    """Test the EmotionalStateTracker."""

    def test_initial_emotion_default(self):
        tracker = EmotionalStateTracker()
        assert tracker.state.current_emotion == "calm"

    def test_initial_emotion_custom(self):
        tracker = EmotionalStateTracker(initial_emotion="analytical")
        assert tracker.state.current_emotion == "analytical"

    def test_initial_emotion_invalid_falls_back(self):
        tracker = EmotionalStateTracker(initial_emotion="invalid_state")
        assert tracker.state.current_emotion == "calm"

    def test_process_known_event(self):
        tracker = EmotionalStateTracker()
        state = tracker.process_event("task_success")
        assert state.current_emotion == "confident"
        assert state.trigger_event == "task_success"
        assert state.previous_emotion == "calm"

    def test_process_unknown_event_ignored(self):
        tracker = EmotionalStateTracker()
        state = tracker.process_event("unknown_event_xyz")
        assert state.current_emotion == "calm"  # unchanged

    def test_repeated_same_emotion_amplifies(self):
        tracker = EmotionalStateTracker()
        tracker.process_event("task_success")
        initial_intensity = tracker.state.intensity
        tracker.process_event("user_praise")  # also targets confident
        assert tracker.state.intensity >= initial_intensity

    def test_different_emotion_replaces(self):
        tracker = EmotionalStateTracker()
        tracker.process_event("task_success")
        assert tracker.state.current_emotion == "confident"
        tracker.process_event("task_failure")
        assert tracker.state.current_emotion == "frustrated"
        assert tracker.state.previous_emotion == "confident"

    def test_decay_no_effect_when_recent(self):
        tracker = EmotionalStateTracker()
        tracker.process_event("task_failure")
        emotion_before = tracker.state.current_emotion
        tracker.decay()
        assert tracker.state.current_emotion == emotion_before

    def test_decay_resets_to_calm_after_long_time(self):
        tracker = EmotionalStateTracker()
        tracker.process_event("task_failure")
        assert tracker.state.current_emotion == "frustrated"

        # Simulate passage of time (30+ minutes)
        tracker.state.updated_at = time.time() - 2000
        tracker.decay()
        assert tracker.state.current_emotion == "calm"

    def test_get_profile_returns_expected_keys(self):
        tracker = EmotionalStateTracker()
        profile = tracker.get_profile()
        assert "current_emotion" in profile
        assert "emotion_label" in profile
        assert "intensity" in profile
        assert "intensity_label" in profile
        assert "previous_emotion" in profile
        assert "trigger_event" in profile
        assert "prompt_modifier" in profile

    def test_get_prompt_modifier_returns_string(self):
        tracker = EmotionalStateTracker(initial_emotion="cautious")
        modifier = tracker.get_prompt_modifier()
        assert isinstance(modifier, str)
        assert "cautious" in modifier.lower()

    def test_reset(self):
        tracker = EmotionalStateTracker()
        tracker.process_event("task_failure")
        tracker.reset()
        assert tracker.state.current_emotion == "calm"
        assert tracker.state.intensity == 0.5

    def test_process_event_with_context(self):
        """Context dict is accepted without error."""
        tracker = EmotionalStateTracker()
        state = tracker.process_event("error", {"details": "connection timeout"})
        assert state.current_emotion == "cautious"

    def test_event_chain_scenario(self):
        """Simulate: task assigned → success → new discovery → idle."""
        tracker = EmotionalStateTracker()

        tracker.process_event("task_assigned")
        assert tracker.state.current_emotion == "analytical"

        tracker.process_event("task_success")
        assert tracker.state.current_emotion == "confident"

        tracker.process_event("new_discovery")
        assert tracker.state.current_emotion == "curious"

        tracker.process_event("idle")
        assert tracker.state.current_emotion == "calm"

    def test_health_events(self):
        tracker = EmotionalStateTracker()
        tracker.process_event("health_low")
        assert tracker.state.current_emotion == "cautious"

        tracker.process_event("health_recovered")
        assert tracker.state.current_emotion == "calm"

    def test_quest_completed_triggers_adventurous(self):
        tracker = EmotionalStateTracker()
        tracker.process_event("quest_completed")
        assert tracker.state.current_emotion == "adventurous"


class TestIntensityLabel:
    def test_overwhelming(self):
        assert _intensity_label(0.9) == "overwhelming"

    def test_strong(self):
        assert _intensity_label(0.7) == "strong"

    def test_moderate(self):
        assert _intensity_label(0.5) == "moderate"

    def test_mild(self):
        assert _intensity_label(0.3) == "mild"

    def test_faint(self):
        assert _intensity_label(0.1) == "faint"
