from unittest.mock import MagicMock, patch

import pytest

from GramAddict.core.bot_flow import _interact_with_profile
from GramAddict.core.telepathic_engine import TelepathicEngine


@pytest.fixture
def mock_device():
    device = MagicMock()
    device.get_info.return_value = {"displayWidth": 1080, "displayHeight": 2400}
    device.dump_hierarchy.return_value = '<?xml version="1.0"?><hierarchy><node resource-id="com.instagram.android:id/row_profile_header_textview_followers_count" text="10.5K" /></hierarchy>'
    device.get_screenshot_b64.return_value = "fake_base64_image_data"

    # Mock args
    class Args:
        scrape_profiles = False
        visual_vibe_check_percentage = "100"
        ai_telepathic_model = "test-model"
        ai_telepathic_url = "http://test-url"
        follow_percentage = "100"
        likes_percentage = "100"
        profile_learning_percentage = "0"

    device.args = Args()
    return device


@pytest.fixture
def mock_configs(mock_device):
    configs = MagicMock()
    configs.args = mock_device.args
    return configs


@patch("GramAddict.core.telepathic_engine.TelepathicEngine.get_instance")
@patch("GramAddict.core.llm_provider.query_llm")
def test_visual_vibe_check_rejects_poor_quality(mock_query_llm, mock_get_instance, mock_device, mock_configs):
    logger = MagicMock()
    session_state = MagicMock()
    session_state.my_username = "my_bot"

    # Use real engine instead of the autouse mock from conftest
    real_engine = TelepathicEngine()
    mock_get_instance.return_value = real_engine

    cognitive_stack = {"persona_interests": ["aesthetic architecture", "minimalism"], "resonance": MagicMock()}

    # Mock VLM response to reject the profile
    mock_query_llm.return_value = {
        "response": '{"quality_score": 3, "matches_niche": false, "reason": "Very generic and spammy looking grid."}'
    }

    # Run interaction flow
    _interact_with_profile(
        device=mock_device,
        configs=mock_configs,
        username="target_user",
        session_state=session_state,
        sleep_mod=1.0,
        logger=logger,
        cognitive_stack=cognitive_stack,
    )

    # Verify screenshot was evaluated
    assert mock_device.get_screenshot_b64.called
    assert mock_query_llm.called

    # Verify the AI reason was logged
    log_messages = [call.args[0] for call in logger.warning.call_args_list]
    assert any("Very generic and spammy looking grid." in msg for msg in log_messages)

    # Verify we did NOT attempt to follow or like (since it was rejected)
    nav_graph_do_calls = [call for call in mock_device.mock_calls if "do" in str(call)]
    assert len(nav_graph_do_calls) == 0  # No interactions executed


@patch("GramAddict.core.telepathic_engine.TelepathicEngine.get_instance")
@patch("GramAddict.core.llm_provider.query_llm")
def test_visual_vibe_check_accepts_high_quality(mock_query_llm, mock_get_instance, mock_device, mock_configs):
    logger = MagicMock()
    session_state = MagicMock()
    session_state.my_username = "my_bot"
    session_state.check_limit.return_value = False

    real_engine = TelepathicEngine()
    mock_get_instance.return_value = real_engine

    cognitive_stack = {"persona_interests": ["aesthetic architecture", "minimalism"], "resonance": MagicMock()}

    # Mock VLM response to accept the profile
    mock_query_llm.return_value = {
        "response": '{"quality_score": 9, "matches_niche": true, "reason": "Beautiful cohesive grid."}'
    }

    # We also have to prevent the nav_graph.do from throwing if we reach it
    with (
        patch("GramAddict.core.q_nav_graph.QNavGraph.do", return_value=True) as mock_do,
        patch("GramAddict.core.behaviors.follow.sleep"),
    ):
        from GramAddict.core.behaviors import PluginRegistry
        from GramAddict.core.behaviors.follow import FollowPlugin

        registry = PluginRegistry.get_instance()
        registry.register(FollowPlugin())

        _interact_with_profile(
            device=mock_device,
            configs=mock_configs,
            username="target_user",
            session_state=session_state,
            sleep_mod=1.0,
            logger=logger,
            cognitive_stack=cognitive_stack,
        )

        # Verify it proceeded to interactions (like/follow)
        assert mock_do.called
