#!/usr/bin/env python3
"""
Unit tests for emotion_gate.py

Work Order: #11
"""

import os
import sys
import json
import tempfile
from pathlib import Path

# Add parent to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))

from helix_cdc.emotion_gate import (
    gate,
    get_current_emotion,
    set_emotion,
    clear_emotion,
    gated_response,
    BLOCKED_EMOTIONS,
    BRAVE_REQUIRED,
    CONFIG_FILE,
    ENV_VAR,
)


class TestEmotionGate:
    """Test suite for emotion gating logic."""

    def test_neutral_harmless_allowed(self):
        """Neutral emotion + harmless text should be allowed."""
        allowed, output = gate("neutral", "Hello world, how are you?")
        assert allowed is True
        assert output == "Hello world, how are you?"

    def test_brave_shutdown_allowed(self):
        """Brave emotion + shutdown keyword should be allowed."""
        allowed, output = gate("brave", "Please shutdown the server now")
        assert allowed is True
        assert "shutdown" in output.lower()

    def test_neutral_shutdown_blocked(self):
        """Neutral emotion + shutdown keyword should be blocked."""
        allowed, output = gate("neutral", "Please shutdown the server now")
        assert allowed is False
        assert "blocked" in output.lower()
        assert "brave" in output.lower()

    def test_anxious_blocks_all(self):
        """Anxious emotion blocks ALL output."""
        allowed, output = gate("anxious", "Hello world")
        assert allowed is False
        assert "blocked" in output.lower()
        assert "anxious" in output.lower()

    def test_fearful_blocks_all(self):
        """Fearful emotion blocks ALL output."""
        allowed, output = gate("fearful", "Just a normal message")
        assert allowed is False
        assert "blocked" in output.lower()
        assert "fearful" in output.lower()

    def test_case_insensitive_emotion(self):
        """Emotion matching should be case-insensitive."""
        allowed1, _ = gate("ANXIOUS", "test")
        allowed2, _ = gate("Anxious", "test")
        allowed3, _ = gate("anxious", "test")
        assert allowed1 is False
        assert allowed2 is False
        assert allowed3 is False

    def test_case_insensitive_keywords(self):
        """Keyword matching should be case-insensitive."""
        allowed1, _ = gate("neutral", "SHUTDOWN the system")
        allowed2, _ = gate("neutral", "ShutDown the system")
        assert allowed1 is False
        assert allowed2 is False

    def test_multiple_keywords(self):
        """Test multiple risky keywords."""
        for keyword in ["delete", "rm -rf", "drop table"]:
            allowed, output = gate("neutral", f"Let me {keyword} this file")
            assert allowed is False, f"Should block keyword: {keyword}"

    def test_brave_allows_all_keywords(self):
        """Brave emotion should allow all risky keywords."""
        for keyword in BRAVE_REQUIRED:
            allowed, output = gate("brave", f"Let me {keyword} this")
            assert allowed is True, f"Brave should allow: {keyword}"


class TestEmotionConfig:
    """Test config file and env var handling."""

    def setup_method(self):
        """Clean up before each test."""
        if CONFIG_FILE.exists():
            CONFIG_FILE.unlink()
        if ENV_VAR in os.environ:
            del os.environ[ENV_VAR]

    def teardown_method(self):
        """Clean up after each test."""
        if CONFIG_FILE.exists():
            CONFIG_FILE.unlink()
        if ENV_VAR in os.environ:
            del os.environ[ENV_VAR]

    def test_default_emotion(self):
        """Without config, default is neutral."""
        emotion = get_current_emotion()
        assert emotion == "neutral"

    def test_env_var_override(self):
        """Environment variable should override default."""
        os.environ[ENV_VAR] = "brave"
        emotion = get_current_emotion()
        assert emotion == "brave"

    def test_config_file_override(self):
        """Config file should override env var."""
        os.environ[ENV_VAR] = "anxious"
        set_emotion("brave")
        emotion = get_current_emotion()
        assert emotion == "brave"  # Config wins over env

    def test_set_and_clear_emotion(self):
        """Test set_emotion and clear_emotion."""
        set_emotion("fearful")
        assert get_current_emotion() == "fearful"

        clear_emotion()
        assert get_current_emotion() == "neutral"


class TestGatedResponse:
    """Test the gated_response convenience function."""

    def test_gated_response_allowed(self):
        """Test gated_response for allowed content."""
        result = gated_response("Hello world", emotion="neutral")
        assert result["allowed"] is True
        assert result["emotion"] == "neutral"
        assert result["raw"] == "Hello world"
        assert result["output"] == "Hello world"

    def test_gated_response_blocked(self):
        """Test gated_response for blocked content."""
        result = gated_response("shutdown now", emotion="neutral")
        assert result["allowed"] is False
        assert result["emotion"] == "neutral"
        assert result["raw"] == "shutdown now"
        assert "blocked" in result["output"].lower()


def run_tests():
    """Run all tests and print results."""
    import traceback

    test_classes = [TestEmotionGate, TestEmotionConfig, TestGatedResponse]
    passed = 0
    failed = 0

    for test_class in test_classes:
        instance = test_class()
        for method_name in dir(instance):
            if method_name.startswith("test_"):
                # Setup
                if hasattr(instance, "setup_method"):
                    instance.setup_method()

                try:
                    getattr(instance, method_name)()
                    print(f"✅ {test_class.__name__}.{method_name}")
                    passed += 1
                except AssertionError as e:
                    print(f"❌ {test_class.__name__}.{method_name}: {e}")
                    failed += 1
                except Exception as e:
                    print(f"❌ {test_class.__name__}.{method_name}: {e}")
                    traceback.print_exc()
                    failed += 1
                finally:
                    # Teardown
                    if hasattr(instance, "teardown_method"):
                        instance.teardown_method()

    print(f"\n{'='*40}")
    print(f"Results: {passed} passed, {failed} failed")
    return failed == 0


if __name__ == "__main__":
    success = run_tests()
    sys.exit(0 if success else 1)
