import os
import sys
from unittest.mock import MagicMock, patch

import pytest

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../")))

from GramAddict.core.goap import GoalExecutor, ScreenType


@pytest.fixture
def mock_device():
    device = MagicMock()
    # Simulate XML changing but screen type not being the target
    device.dump_hierarchy.side_effect = ["<xml1/>", "<xml2/>", "<xml2/>"]
    device.app_id = "com.instagram.android"
    return device


@pytest.fixture
def mock_telepathic():
    with patch("GramAddict.core.telepathic_engine.TelepathicEngine.get_instance") as mock:
        engine = mock.return_value
        engine.find_best_node.return_value = {"x": 100, "y": 200, "semantic_string": "mock_node"}
        yield engine


def test_execution_rejects_wrong_screen(mock_device, mock_telepathic):
    """
    TDD Case: If we intend to go to DMs but land on Reels,
    TelepathicEngine.confirm_click should NOT be called.
    """
    executor = GoalExecutor(mock_device, "testuser")

    # We mock perceive to return ReelsFeed after the click
    with patch.object(executor, "perceive") as mock_perceive:
        # Before click
        mock_perceive.side_effect = [
            {"screen_type": ScreenType.HOME_FEED},  # Initial
            {"screen_type": ScreenType.REELS_FEED},  # After click (WRONG!)
        ]

        # Action that intends to go to DM_INBOX
        action = "tap messages tab"

        # We need to make sure _execute_action knows the goal is "open messages"
        # Since _execute_action is usually called from achieve(), we mock that flow

        success = executor._execute_action(action, goal="open messages")

        # Success should be False because we didn't reach the goal
        # (Or True if we only care about XML change, but that's what we're changing)
        assert success is False

        # CRITICAL: confirm_click should NOT have been called for 'messages tab'
        # since we are on Reels.
        mock_telepathic.confirm_click.assert_not_called()
        mock_telepathic.reject_click.assert_called_once_with(action)
