from unittest.mock import MagicMock, patch

import pytest

from GramAddict.core.behaviors.grid_like import GridLikePlugin


@pytest.fixture
def grid_like_plugin():
    return GridLikePlugin()


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

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

    ctx.context_xml = '<xml><node content-desc="profile_header" text="followers"/></xml>'
    ctx.device = MagicMock()
    ctx.device.get_info.return_value = {"displayWidth": 1080, "displayHeight": 2400}
    ctx.device.dump_hierarchy.return_value = "<xml></xml>"
    ctx.username = "test_user"
    ctx.sleep_mod = 1.0

    growth_brain = MagicMock()
    growth_brain.wants_to_double_tap.return_value = False
    ctx.cognitive_stack = {"growth_brain": growth_brain}
    return ctx


class TestGridLikePlugin:
    def test_can_activate_enabled(self, grid_like_plugin, mock_context):
        assert grid_like_plugin.can_activate(mock_context) is True

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

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

    def test_can_activate_wrong_screen(self, grid_like_plugin, mock_context):
        mock_context.context_xml = '<xml><node content-desc="home_feed"/></xml>'
        assert grid_like_plugin.can_activate(mock_context) is False

    @patch("random.random", return_value=0.1)
    @patch("GramAddict.core.q_nav_graph.QNavGraph")
    @patch("GramAddict.core.behaviors.grid_like.wait_for_post_loaded", return_value=True)
    @patch("GramAddict.core.behaviors.grid_like.humanized_scroll")
    @patch("GramAddict.core.behaviors.grid_like.humanized_click")
    @patch("GramAddict.core.behaviors.grid_like.sleep")
    def test_execute_success_heart_button(
        self,
        mock_sleep,
        mock_click,
        mock_scroll,
        mock_wait,
        mock_qnavgraph,
        mock_random,
        grid_like_plugin,
        mock_context,
    ):
        mock_nav = MagicMock()
        mock_nav.do.return_value = True  # tap first image post AND tap like button
        mock_qnavgraph.return_value = mock_nav

        result = grid_like_plugin.execute(mock_context)

        assert result.executed is True
        assert result.interactions == 2
        assert mock_context.session_state.totalLikes == 2

        mock_nav.do.assert_any_call("tap first image post in profile grid")
        mock_nav.do.assert_any_call("tap like button")
        mock_context.device.press.assert_called_once_with("back")

    @patch("random.random", return_value=0.1)
    @patch("GramAddict.core.q_nav_graph.QNavGraph")
    @patch("GramAddict.core.behaviors.grid_like.wait_for_post_loaded", return_value=True)
    @patch("GramAddict.core.behaviors.grid_like.humanized_scroll")
    @patch("GramAddict.core.behaviors.grid_like.humanized_click")
    @patch("GramAddict.core.behaviors.grid_like.sleep")
    def test_execute_success_double_tap(
        self,
        mock_sleep,
        mock_click,
        mock_scroll,
        mock_wait,
        mock_qnavgraph,
        mock_random,
        grid_like_plugin,
        mock_context,
    ):
        mock_nav = MagicMock()
        mock_nav.do.return_value = True
        mock_qnavgraph.return_value = mock_nav

        mock_context.cognitive_stack["growth_brain"].wants_to_double_tap.return_value = True

        result = grid_like_plugin.execute(mock_context)

        assert result.executed is True
        assert result.interactions == 2
        assert mock_context.session_state.totalLikes == 2

        mock_click.assert_called()

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

        result = grid_like_plugin.execute(mock_context)

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