from unittest.mock import MagicMock, patch

import pytest

from GramAddict.core.behaviors.story_view import StoryViewPlugin


@pytest.fixture
def story_view_plugin():
    return StoryViewPlugin()


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

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

    ctx.cognitive_stack = {}
    return ctx


class TestStoryViewPlugin:
    def test_can_activate_enabled(self, story_view_plugin, mock_context):
        assert story_view_plugin.can_activate(mock_context) is True

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

    @patch("random.random", return_value=0.1)
    def test_execute_no_story_in_xml(self, mock_random, story_view_plugin, mock_context):
        mock_context.context_xml = "<xml></xml>"
        mock_context.device.dump_hierarchy.return_value = "<xml></xml>"
        result = story_view_plugin.execute(mock_context)

        assert result.executed is False
        assert result.metadata["reason"] == "no_story"

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

        result = story_view_plugin.execute(mock_context)

        assert result.executed is False
        assert result.metadata["reason"] == "nav_failed"

    @patch("random.random", return_value=0.1)
    @patch("GramAddict.core.q_nav_graph.QNavGraph")
    @patch("GramAddict.core.behaviors.story_view.wait_for_story_loaded", return_value=False)
    def test_execute_load_timeout(self, mock_wait, mock_qnavgraph, mock_random, story_view_plugin, mock_context):
        mock_nav = MagicMock()
        mock_nav.do.return_value = True
        mock_qnavgraph.return_value = mock_nav

        result = story_view_plugin.execute(mock_context)

        assert result.executed is False
        assert result.metadata["reason"] == "load_timeout"

    @patch("random.random", return_value=0.1)
    @patch("GramAddict.core.q_nav_graph.QNavGraph")
    @patch("GramAddict.core.behaviors.story_view.wait_for_story_loaded", return_value=True)
    @patch("GramAddict.core.behaviors.story_view.humanized_click")
    @patch("GramAddict.core.behaviors.story_view.sleep")
    def test_execute_success(
        self, mock_sleep, mock_click, mock_wait, mock_qnavgraph, mock_random, story_view_plugin, mock_context
    ):
        mock_nav = MagicMock()
        mock_nav.do.return_value = True
        mock_qnavgraph.return_value = mock_nav

        result = story_view_plugin.execute(mock_context)

        assert result.executed is True
        assert result.interactions == 2
        assert result.metadata["stories_viewed"] == 2

        # 2 stories, so 1 click (to advance from 1st to 2nd)
        mock_click.assert_called_once()
        mock_context.device.press.assert_called_once_with("back")
