from unittest.mock import MagicMock, patch

import pytest

from GramAddict.core.behaviors.follow import FollowPlugin


@pytest.fixture
def follow_plugin():
    return FollowPlugin()


@pytest.fixture
def mock_context():
    ctx = MagicMock()
    ctx.configs = MagicMock()
    ctx.configs.get_plugin_config.return_value = {"percentage": 100}

    ctx.session_state = MagicMock()
    ctx.session_state.check_limit.return_value = False

    ctx.device = MagicMock()
    ctx.username = "test_user"
    ctx.sleep_mod = 1.0

    ctx.cognitive_stack = {}
    return ctx


class TestFollowPlugin:
    @patch("random.random", return_value=0.1)
    def test_can_activate_enabled(self, mock_random, follow_plugin, mock_context):
        assert follow_plugin.can_activate(mock_context) is True
        mock_context.session_state.check_limit.assert_called_once()

    def test_can_activate_disabled_via_config(self, follow_plugin, mock_context):
        mock_context.configs.get_plugin_config.return_value = {"percentage": 0}
        assert follow_plugin.can_activate(mock_context) is False

    def test_can_activate_limit_reached(self, follow_plugin, mock_context):
        mock_context.session_state.check_limit.return_value = True
        assert follow_plugin.can_activate(mock_context) is False

    @patch("GramAddict.core.q_nav_graph.QNavGraph")
    @patch("GramAddict.core.behaviors.follow.sleep")
    def test_execute_success(self, mock_sleep, mock_qnavgraph, follow_plugin, mock_context):
        mock_nav = MagicMock()
        mock_nav.do.return_value = True
        mock_qnavgraph.return_value = mock_nav

        result = follow_plugin.execute(mock_context)

        assert result.executed is True
        assert result.interactions == 1

        mock_nav.do.assert_called_once_with("tap follow button")

    @patch("GramAddict.core.q_nav_graph.QNavGraph")
    def test_execute_nav_failed(self, mock_qnavgraph, follow_plugin, mock_context):
        mock_nav = MagicMock()
        mock_nav.do.return_value = False
        mock_qnavgraph.return_value = mock_nav

        result = follow_plugin.execute(mock_context)

        assert result.executed is False
        assert result.metadata.get("reason") == "nav_failed"
