from unittest import mock
from unittest.mock import MagicMock, create_autospec, patch

import pytest

from GramAddict.core.behaviors import BehaviorContext
from GramAddict.core.behaviors.resonance_evaluator import ResonanceEvaluatorPlugin


@pytest.fixture
def resonance_evaluator():
    return ResonanceEvaluatorPlugin()


@pytest.fixture
def mock_context():
    configs = MagicMock()
    configs.args.visual_vibe_check_percentage = 0
    configs.args.interact_percentage = 100  # Never skip

    ctx = BehaviorContext(
        device=MagicMock(),
        configs=configs,
        session_state=MagicMock(),
        cognitive_stack={"resonance": MagicMock(), "dopamine": MagicMock()},
        context_xml="<xml></xml>",
        post_data={"username": "test_user"},
        username="test_user",
        shared_state={"session_outcomes": []},
    )
    return ctx


class TestResonanceEvaluatorPlugin:
    def test_execute_high_resonance(self, resonance_evaluator, mock_context):
        mock_context.cognitive_stack["resonance"].calculate_resonance.return_value = 0.9

        result = resonance_evaluator.execute(mock_context)

        assert result.executed is True
        assert result.should_skip is False
        assert mock_context.shared_state["res_score"] == 0.9
        mock_context.cognitive_stack["dopamine"].process_content.assert_called_once_with(
            {"score": 9.0, "quality": "high"}
        )

    @patch("GramAddict.core.behaviors.resonance_evaluator.humanized_scroll")
    @patch("GramAddict.core.behaviors.resonance_evaluator.sleep")
    def test_execute_low_resonance_skip(self, mock_sleep, mock_scroll, resonance_evaluator, mock_context):
        mock_context.configs.args.interact_percentage = 0  # Force skip
        mock_context.cognitive_stack["resonance"].calculate_resonance.return_value = 0.1

        # Mock random so it always skips
        with patch("GramAddict.core.behaviors.resonance_evaluator.random.random", return_value=0.0):
            result = resonance_evaluator.execute(mock_context)

        assert result.executed is True
        assert result.should_skip is True
        mock_scroll.assert_called_once_with(mock_context.device)
        assert len(mock_context.shared_state["session_outcomes"]) == 1
        assert mock_context.shared_state["session_outcomes"][0]["resonance"] == 0.1
        assert mock_context.shared_state["session_outcomes"][0]["action"] == "skip"

    @patch("GramAddict.core.behaviors.resonance_evaluator.humanized_scroll")
    @patch("GramAddict.core.behaviors.resonance_evaluator.sleep")
    def test_execute_visual_vibe_check(self, mock_sleep, mock_scroll, resonance_evaluator, mock_context):
        from GramAddict.core.telepathic_engine import TelepathicEngine

        mock_context.configs.args.visual_vibe_check_percentage = 100
        mock_context.cognitive_stack["resonance"].calculate_resonance.return_value = 0.5

        mock_tele = create_autospec(TelepathicEngine, instance=True)
        mock_tele.evaluate_post_vibe.return_value = {"quality_score": 10, "matches_niche": True}
        mock_context.cognitive_stack["telepathic"] = mock_tele

        with patch("GramAddict.core.behaviors.resonance_evaluator.random.random", return_value=0.0):
            result = resonance_evaluator.execute(mock_context)

        assert result.executed is True
        assert result.should_skip is False
        # res_score = 0.5 * 0.3 + 1.0 * 0.7 = 0.15 + 0.70 = 0.85
        assert round(mock_context.shared_state["res_score"], 2) == 0.85
        mock_tele.evaluate_post_vibe.assert_called_once_with(mock_context.device, mock.ANY)
