"""
Shared fixtures for strategy testing.

These fixtures provide mocked LLM and search components that allow testing
strategies without making real API calls.
"""

import json
from unittest.mock import Mock

import pytest


# ============== Strategy-specific Mock LLM ==============


def create_mock_llm_response(content: str) -> Mock:
    """Create a mock LLM response object."""
    response = Mock()
    response.content = content
    return response


@pytest.fixture
def strategy_mock_llm():
    """
    Create a mock LLM that returns structured responses suitable for strategy testing.

    The mock handles different types of prompts by pattern matching and returning
    appropriate responses for question generation, analysis, and synthesis.
    """
    mock = Mock()

    def invoke_side_effect(prompt, *args, **kwargs):
        # Convert prompt to string if it's a list of messages
        if isinstance(prompt, list):
            prompt_text = " ".join(
                msg.content if hasattr(msg, "content") else str(msg)
                for msg in prompt
            )
        else:
            prompt_text = str(prompt)

        prompt_lower = prompt_text.lower()

        # Topic organization - expects simple responses like "0", "1", "-", "d"
        # Check this first as these prompts may also contain other keywords
        if (
            "source to categorize" in prompt_lower
            or "existing topics" in prompt_lower
        ):
            # If no topics exist yet, return "-" to create a new topic
            if "no topics yet" in prompt_lower:
                return create_mock_llm_response("-")
            # Otherwise, add to topic 0
            return create_mock_llm_response("0")

        # Question generation
        if "question" in prompt_lower and (
            "generate" in prompt_lower or "research" in prompt_lower
        ):
            return create_mock_llm_response(
                "1. What are the key aspects of this topic?\n"
                "2. How has this evolved over time?\n"
                "3. What are the main challenges?"
            )

        # Analysis/synthesis
        if (
            "analyze" in prompt_lower
            or "synthesize" in prompt_lower
            or "summarize" in prompt_lower
        ):
            return create_mock_llm_response(
                "Based on the available information, the key findings are:\n"
                "1. Topic has multiple dimensions\n"
                "2. Research shows various perspectives\n"
                "3. Further investigation may be needed"
            )

        # Constraint extraction
        if "constraint" in prompt_lower or "extract" in prompt_lower:
            return create_mock_llm_response(
                json.dumps(
                    {
                        "constraints": [
                            {"type": "temporal", "value": "recent"},
                            {"type": "geographic", "value": "global"},
                        ]
                    }
                )
            )

        # Candidate generation
        if "candidate" in prompt_lower or "entity" in prompt_lower:
            return create_mock_llm_response(
                json.dumps(
                    {
                        "candidates": [
                            "Candidate A",
                            "Candidate B",
                            "Candidate C",
                        ]
                    }
                )
            )

        # Confidence/evaluation
        if (
            "confidence" in prompt_lower
            or "evaluate" in prompt_lower
            or "score" in prompt_lower
        ):
            return create_mock_llm_response(
                json.dumps(
                    {
                        "confidence": 0.75,
                        "evaluation": "Moderate confidence based on available evidence",
                    }
                )
            )

        # Classification
        if "classify" in prompt_lower or "type" in prompt_lower:
            return create_mock_llm_response(
                json.dumps({"type": "research", "complexity": "moderate"})
            )

        # Default response
        return create_mock_llm_response(
            "This is a mocked LLM response for testing purposes. "
            "The topic requires further research and analysis."
        )

    mock.invoke = Mock(side_effect=invoke_side_effect)

    # Also support __call__ for some LLM implementations
    mock.__call__ = mock.invoke

    # Add common attributes that LLMs might have
    mock.model_name = "mock-model"
    mock.temperature = 0.7

    return mock


@pytest.fixture
def strategy_mock_search():
    """
    Create a mock search engine that returns realistic search results.
    """
    mock = Mock()

    search_results = [
        {
            "title": "Research Article on Topic",
            "link": "https://example.com/article1",
            "snippet": "This article discusses various aspects of the topic including methodology and findings.",
            "full_content": "Full content of the research article discussing the topic in detail.",
        },
        {
            "title": "Wikipedia: Topic Overview",
            "link": "https://en.wikipedia.org/wiki/Topic",
            "snippet": "Topic is a subject of research with multiple dimensions and applications.",
            "full_content": "Wikipedia article providing comprehensive overview of the topic.",
        },
        {
            "title": "Academic Paper on Related Research",
            "link": "https://arxiv.org/abs/1234.5678",
            "snippet": "This paper presents new findings related to the topic and its implications.",
            "full_content": "Academic paper with detailed analysis and results.",
        },
    ]

    mock.run = Mock(return_value=search_results)
    mock.include_full_content = True

    return mock


@pytest.fixture
def strategy_settings_snapshot():
    """
    Create a standard settings snapshot for strategy testing.
    """
    return {
        # Search settings
        "search.iterations": {"value": 2, "type": "int"},
        "search.questions_per_iteration": {"value": 3, "type": "int"},
        "search.questions": {"value": 3, "type": "int"},
        "search.final_max_results": {"value": 100, "type": "int"},
        "search.cross_engine_max_results": {"value": 100, "type": "int"},
        "search.cross_engine_use_reddit": {"value": False, "type": "bool"},
        "search.cross_engine_min_date": {"value": None, "type": "str"},
        # LLM settings
        "llm.provider": {"value": "mock", "type": "str"},
        "llm.model": {"value": "mock-model", "type": "str"},
        # Search tool settings
        "search.tool": {"value": "mock", "type": "str"},
        # App settings
        "app.max_user_query_length": {"value": 300, "type": "int"},
        # General settings
        "general.knowledge_accumulation_context_limit": {
            "value": 5000,
            "type": "int",
        },
        "general.max_knowledge_items": {"value": 100, "type": "int"},
        # Focused iteration settings
        "focused_iteration.adaptive_questions": {"value": 0, "type": "int"},
        "focused_iteration.knowledge_summary_limit": {
            "value": 10,
            "type": "int",
        },
        "focused_iteration.snippet_truncate": {"value": 200, "type": "int"},
        "focused_iteration.question_generator": {
            "value": "browsecomp",
            "type": "str",
        },
        "focused_iteration.prompt_knowledge_truncate": {
            "value": 1500,
            "type": "int",
        },
        "focused_iteration.previous_searches_limit": {
            "value": 10,
            "type": "int",
        },
    }


# ============== Strategy Names for Parametrized Tests ==============


# All strategy names supported by the factory
FACTORY_STRATEGY_NAMES = [
    "source-based",
    "focused-iteration",
    "focused-iteration-standard",
    "news",
    "topic-organization",
    "langgraph-agent",
]


# Strategy classes that can be imported directly
STRATEGY_IMPORTS = [
    ("source_based_strategy", "SourceBasedSearchStrategy"),
    ("focused_iteration_strategy", "FocusedIterationStrategy"),
    ("news_strategy", "NewsAggregationStrategy"),
    ("topic_organization_strategy", "TopicOrganizationStrategy"),
    ("langgraph_agent_strategy", "LangGraphAgentStrategy"),
]
