"""
Factory for creating search strategies.
This module provides a centralized way to create search strategies
to avoid code duplication.
"""

from loguru import logger
from typing import Optional, Dict, Any, List
from langchain_core.language_models import BaseChatModel

# Re-export from constants so existing importers don't break
from .constants import (  # noqa: F401
    ALL_STRATEGIES,
    AVAILABLE_STRATEGIES,
    get_available_strategies,
)


def _get_setting(
    settings_snapshot: Optional[Dict], key: str, default: Any
) -> Any:
    """Get a setting value from the snapshot, handling nested dict structure."""
    if not settings_snapshot or key not in settings_snapshot:
        return default
    value = settings_snapshot[key]
    # Extract value from dict structure if needed
    if isinstance(value, dict) and "value" in value:
        return value["value"]
    return value


def create_strategy(
    strategy_name: str,
    model: BaseChatModel,
    search: Any,
    all_links_of_system: Optional[List[Dict]] = None,
    settings_snapshot: Optional[Dict] = None,
    research_context: Optional[Dict] = None,
    **kwargs,
):
    """
    Create a search strategy by name.

    Args:
        strategy_name: Name of the strategy to create
        model: Language model to use
        search: Search engine instance
        all_links_of_system: List of existing links
        settings_snapshot: Settings snapshot
        research_context: Research context for special strategies
        **kwargs: Additional strategy-specific parameters

    Returns:
        Strategy instance
    """
    if all_links_of_system is None:
        all_links_of_system = []

    strategy_name_lower = strategy_name.lower()

    # Source-based strategy
    if strategy_name_lower in [
        "source-based",
        "source_based",
        "source_based_search",
    ]:
        from .advanced_search_system.strategies.source_based_strategy import (
            SourceBasedSearchStrategy,
        )

        return SourceBasedSearchStrategy(
            model=model,
            search=search,
            include_text_content=kwargs.get("include_text_content", True),
            use_cross_engine_filter=kwargs.get("use_cross_engine_filter", True),
            all_links_of_system=all_links_of_system,
            use_atomic_facts=kwargs.get("use_atomic_facts", False),
            settings_snapshot=settings_snapshot,
            search_original_query=kwargs.get("search_original_query", True),
        )

    # Focused iteration strategy
    if strategy_name_lower in ["focused-iteration", "focused_iteration"]:
        from .advanced_search_system.strategies.focused_iteration_strategy import (
            FocusedIterationStrategy,
        )

        # Read focused_iteration settings with kwargs override
        # adaptive_questions is stored as 0/1 integer, convert to bool
        enable_adaptive = bool(
            kwargs.get(
                "enable_adaptive_questions",
                _get_setting(
                    settings_snapshot, "focused_iteration.adaptive_questions", 0
                ),
            )
        )
        knowledge_limit = kwargs.get(
            "knowledge_summary_limit",
            _get_setting(
                settings_snapshot,
                "focused_iteration.knowledge_summary_limit",
                10,
            ),
        )
        snippet_truncate = kwargs.get(
            "knowledge_snippet_truncate",
            _get_setting(
                settings_snapshot, "focused_iteration.snippet_truncate", 200
            ),
        )
        question_gen_type = kwargs.get(
            "question_generator",
            _get_setting(
                settings_snapshot,
                "focused_iteration.question_generator",
                "browsecomp",
            ),
        )
        prompt_knowledge_truncate = kwargs.get(
            "prompt_knowledge_truncate",
            _get_setting(
                settings_snapshot,
                "focused_iteration.prompt_knowledge_truncate",
                1500,
            ),
        )
        previous_searches_limit = kwargs.get(
            "previous_searches_limit",
            _get_setting(
                settings_snapshot,
                "focused_iteration.previous_searches_limit",
                10,
            ),
        )
        # Convert 0 to None for "unlimited"
        if knowledge_limit == 0:
            knowledge_limit = None
        if snippet_truncate == 0:
            snippet_truncate = None
        if prompt_knowledge_truncate == 0:
            prompt_knowledge_truncate = None
        if previous_searches_limit == 0:
            previous_searches_limit = None

        strategy = FocusedIterationStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 8),
            questions_per_iteration=kwargs.get("questions_per_iteration", 5),
            settings_snapshot=settings_snapshot,
            # Options read from settings (with kwargs override)
            enable_adaptive_questions=enable_adaptive,
            enable_early_termination=kwargs.get(
                "enable_early_termination", False
            ),
            knowledge_summary_limit=knowledge_limit,
            knowledge_snippet_truncate=snippet_truncate,
            prompt_knowledge_truncate=prompt_knowledge_truncate,
            previous_searches_limit=previous_searches_limit,
        )

        # Override question generator if flexible is selected
        if question_gen_type == "flexible":
            from .advanced_search_system.questions.flexible_browsecomp_question import (
                FlexibleBrowseCompQuestionGenerator,
            )

            # Pass truncation settings to flexible generator
            strategy.question_generator = FlexibleBrowseCompQuestionGenerator(
                model,
                knowledge_truncate_length=prompt_knowledge_truncate,
                previous_searches_limit=previous_searches_limit,
            )

        return strategy

    # Focused iteration strategy with standard citation handler
    if strategy_name_lower in [
        "focused-iteration-standard",
        "focused_iteration_standard",
    ]:
        from .advanced_search_system.strategies.focused_iteration_strategy import (
            FocusedIterationStrategy,
        )
        from .citation_handler import CitationHandler

        # Use standard citation handler (same question generator as regular focused-iteration)
        standard_citation_handler = CitationHandler(
            model, handler_type="standard", settings_snapshot=settings_snapshot
        )

        # Read focused_iteration settings with kwargs override
        # adaptive_questions is stored as 0/1 integer, convert to bool
        enable_adaptive = bool(
            kwargs.get(
                "enable_adaptive_questions",
                _get_setting(
                    settings_snapshot, "focused_iteration.adaptive_questions", 0
                ),
            )
        )
        knowledge_limit = kwargs.get(
            "knowledge_summary_limit",
            _get_setting(
                settings_snapshot,
                "focused_iteration.knowledge_summary_limit",
                10,
            ),
        )
        snippet_truncate = kwargs.get(
            "knowledge_snippet_truncate",
            _get_setting(
                settings_snapshot, "focused_iteration.snippet_truncate", 200
            ),
        )
        question_gen_type = kwargs.get(
            "question_generator",
            _get_setting(
                settings_snapshot,
                "focused_iteration.question_generator",
                "browsecomp",
            ),
        )
        prompt_knowledge_truncate = kwargs.get(
            "prompt_knowledge_truncate",
            _get_setting(
                settings_snapshot,
                "focused_iteration.prompt_knowledge_truncate",
                1500,
            ),
        )
        previous_searches_limit = kwargs.get(
            "previous_searches_limit",
            _get_setting(
                settings_snapshot,
                "focused_iteration.previous_searches_limit",
                10,
            ),
        )
        # Convert 0 to None for "unlimited"
        if knowledge_limit == 0:
            knowledge_limit = None
        if snippet_truncate == 0:
            snippet_truncate = None
        if prompt_knowledge_truncate == 0:
            prompt_knowledge_truncate = None
        if previous_searches_limit == 0:
            previous_searches_limit = None

        strategy = FocusedIterationStrategy(
            model=model,
            search=search,
            citation_handler=standard_citation_handler,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 8),
            questions_per_iteration=kwargs.get("questions_per_iteration", 5),
            use_browsecomp_optimization=True,  # Keep BrowseComp features
            settings_snapshot=settings_snapshot,
            # Options read from settings (with kwargs override)
            enable_adaptive_questions=enable_adaptive,
            enable_early_termination=kwargs.get(
                "enable_early_termination", False
            ),
            knowledge_summary_limit=knowledge_limit,
            knowledge_snippet_truncate=snippet_truncate,
            prompt_knowledge_truncate=prompt_knowledge_truncate,
            previous_searches_limit=previous_searches_limit,
        )

        # Override question generator if flexible is selected
        if question_gen_type == "flexible":
            from .advanced_search_system.questions.flexible_browsecomp_question import (
                FlexibleBrowseCompQuestionGenerator,
            )

            # Pass truncation settings to flexible generator
            strategy.question_generator = FlexibleBrowseCompQuestionGenerator(
                model,
                knowledge_truncate_length=prompt_knowledge_truncate,
                previous_searches_limit=previous_searches_limit,
            )

        return strategy

    # Iterative reasoning strategy (depth variant)
    if strategy_name_lower in [
        "iterative-reasoning",
        "iterative_reasoning",
        "iterative_reasoning_depth",
    ]:
        from .advanced_search_system.strategies.iterative_reasoning_strategy import (
            IterativeReasoningStrategy,
        )

        return IterativeReasoningStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
        )

    # News aggregation strategy
    if strategy_name_lower in [
        "news",
        "news_aggregation",
        "news-aggregation",
    ]:
        from .advanced_search_system.strategies.news_strategy import (
            NewsAggregationStrategy,
        )

        return NewsAggregationStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
        )

    # IterDRAG strategy
    if strategy_name_lower == "iterdrag":
        from .advanced_search_system.strategies.iterdrag_strategy import (
            IterDRAGStrategy,
        )

        return IterDRAGStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            settings_snapshot=settings_snapshot,
        )

    # Parallel strategy
    if strategy_name_lower == "parallel":
        from .advanced_search_system.strategies.parallel_search_strategy import (
            ParallelSearchStrategy,
        )

        return ParallelSearchStrategy(
            model=model,
            search=search,
            include_text_content=kwargs.get("include_text_content", True),
            use_cross_engine_filter=kwargs.get("use_cross_engine_filter", True),
            all_links_of_system=all_links_of_system,
            settings_snapshot=settings_snapshot,
        )

    # Rapid strategy
    if strategy_name_lower == "rapid":
        from .advanced_search_system.strategies.rapid_search_strategy import (
            RapidSearchStrategy,
        )

        return RapidSearchStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            settings_snapshot=settings_snapshot,
        )

    # Recursive decomposition strategy
    if strategy_name_lower in ["recursive", "recursive-decomposition"]:
        from .advanced_search_system.strategies.recursive_decomposition_strategy import (
            RecursiveDecompositionStrategy,
        )

        return RecursiveDecompositionStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            settings_snapshot=settings_snapshot,
        )

    # Iterative reasoning strategy (different from iterative_reasoning_depth)
    if strategy_name_lower == "iterative":
        from .advanced_search_system.strategies.iterative_reasoning_strategy import (
            IterativeReasoningStrategy,
        )

        # Get iteration settings from kwargs or use defaults
        max_iterations = kwargs.get("max_iterations", 20)
        questions_per_iteration = kwargs.get("questions_per_iteration", 3)
        search_iterations_per_round = kwargs.get(
            "search_iterations_per_round", 1
        )

        return IterativeReasoningStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=max_iterations,
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            search_iterations_per_round=search_iterations_per_round,
            questions_per_search=questions_per_iteration,
            settings_snapshot=settings_snapshot,
        )

    # Adaptive decomposition strategy
    if strategy_name_lower == "adaptive":
        from .advanced_search_system.strategies.adaptive_decomposition_strategy import (
            AdaptiveDecompositionStrategy,
        )

        return AdaptiveDecompositionStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_steps=kwargs.get("max_steps", kwargs.get("max_iterations", 5)),
            min_confidence=kwargs.get("min_confidence", 0.8),
            source_search_iterations=kwargs.get("source_search_iterations", 2),
            source_questions_per_iteration=kwargs.get(
                "source_questions_per_iteration",
                kwargs.get("questions_per_iteration", 3),
            ),
            settings_snapshot=settings_snapshot,
        )

    # Smart decomposition strategy
    if strategy_name_lower == "smart":
        from .advanced_search_system.strategies.smart_decomposition_strategy import (
            SmartDecompositionStrategy,
        )

        return SmartDecompositionStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 5),
            source_search_iterations=kwargs.get("source_search_iterations", 2),
            source_questions_per_iteration=kwargs.get(
                "source_questions_per_iteration",
                kwargs.get("questions_per_iteration", 3),
            ),
            settings_snapshot=settings_snapshot,
        )

    # BrowseComp optimized strategy
    if strategy_name_lower == "browsecomp":
        from .advanced_search_system.strategies.browsecomp_optimized_strategy import (
            BrowseCompOptimizedStrategy,
        )

        return BrowseCompOptimizedStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_browsecomp_iterations=kwargs.get(
                "max_browsecomp_iterations", 15
            ),
            confidence_threshold=kwargs.get("confidence_threshold", 0.9),
            max_iterations=kwargs.get("max_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            settings_snapshot=settings_snapshot,
        )

    # Enhanced evidence-based strategy
    if strategy_name_lower == "evidence":
        from .advanced_search_system.strategies.evidence_based_strategy_v2 import (
            EnhancedEvidenceBasedStrategy,
        )

        return EnhancedEvidenceBasedStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 20),
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            candidate_limit=kwargs.get("candidate_limit", 20),
            evidence_threshold=kwargs.get("evidence_threshold", 0.9),
            max_search_iterations=kwargs.get("max_search_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            min_candidates_threshold=kwargs.get("min_candidates_threshold", 10),
            enable_pattern_learning=kwargs.get("enable_pattern_learning", True),
            settings_snapshot=settings_snapshot,
        )

    # Constrained search strategy
    if strategy_name_lower == "constrained":
        from .advanced_search_system.strategies.constrained_search_strategy import (
            ConstrainedSearchStrategy,
        )

        return ConstrainedSearchStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 20),
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            candidate_limit=kwargs.get("candidate_limit", 100),
            evidence_threshold=kwargs.get("evidence_threshold", 0.9),
            max_search_iterations=kwargs.get("max_search_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            min_candidates_per_stage=kwargs.get("min_candidates_per_stage", 20),
            settings_snapshot=settings_snapshot,
        )

    # Parallel constrained strategy
    if strategy_name_lower in [
        "parallel-constrained",
        "parallel_constrained",
    ]:
        from .advanced_search_system.strategies.parallel_constrained_strategy import (
            ParallelConstrainedStrategy,
        )

        return ParallelConstrainedStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 20),
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            candidate_limit=kwargs.get("candidate_limit", 100),
            evidence_threshold=kwargs.get("evidence_threshold", 0.9),
            max_search_iterations=kwargs.get("max_search_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            min_candidates_per_stage=kwargs.get("min_candidates_per_stage", 20),
            parallel_workers=kwargs.get("parallel_workers", 100),
            settings_snapshot=settings_snapshot,
        )

    # Early stop constrained strategy
    if strategy_name_lower in [
        "early-stop-constrained",
        "early_stop_constrained",
    ]:
        from .advanced_search_system.strategies.early_stop_constrained_strategy import (
            EarlyStopConstrainedStrategy,
        )

        return EarlyStopConstrainedStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 20),
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            candidate_limit=kwargs.get("candidate_limit", 100),
            evidence_threshold=kwargs.get("evidence_threshold", 0.9),
            max_search_iterations=kwargs.get("max_search_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            min_candidates_per_stage=kwargs.get("min_candidates_per_stage", 20),
            parallel_workers=kwargs.get("parallel_workers", 100),
            early_stop_threshold=kwargs.get("early_stop_threshold", 0.99),
            concurrent_evaluation=kwargs.get("concurrent_evaluation", True),
            settings_snapshot=settings_snapshot,
        )

    # Smart query strategy
    if strategy_name_lower in ["smart-query", "smart_query"]:
        from .advanced_search_system.strategies.smart_query_strategy import (
            SmartQueryStrategy,
        )

        return SmartQueryStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 20),
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            candidate_limit=kwargs.get("candidate_limit", 100),
            evidence_threshold=kwargs.get("evidence_threshold", 0.9),
            max_search_iterations=kwargs.get("max_search_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            min_candidates_per_stage=kwargs.get("min_candidates_per_stage", 20),
            parallel_workers=kwargs.get("parallel_workers", 100),
            early_stop_threshold=kwargs.get("early_stop_threshold", 0.99),
            concurrent_evaluation=kwargs.get("concurrent_evaluation", True),
            use_llm_query_generation=kwargs.get(
                "use_llm_query_generation", True
            ),
            queries_per_combination=kwargs.get("queries_per_combination", 3),
            settings_snapshot=settings_snapshot,
        )

    # Dual confidence strategy
    if strategy_name_lower in ["dual-confidence", "dual_confidence"]:
        from .advanced_search_system.strategies.dual_confidence_strategy import (
            DualConfidenceStrategy,
        )

        return DualConfidenceStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 20),
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            candidate_limit=kwargs.get("candidate_limit", 100),
            evidence_threshold=kwargs.get("evidence_threshold", 0.9),
            max_search_iterations=kwargs.get("max_search_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            min_candidates_per_stage=kwargs.get("min_candidates_per_stage", 20),
            parallel_workers=kwargs.get("parallel_workers", 100),
            early_stop_threshold=kwargs.get("early_stop_threshold", 0.95),
            concurrent_evaluation=kwargs.get("concurrent_evaluation", True),
            use_llm_query_generation=kwargs.get(
                "use_llm_query_generation", True
            ),
            queries_per_combination=kwargs.get("queries_per_combination", 3),
            use_entity_seeding=kwargs.get("use_entity_seeding", True),
            use_direct_property_search=kwargs.get(
                "use_direct_property_search", True
            ),
            uncertainty_penalty=kwargs.get("uncertainty_penalty", 0.2),
            negative_weight=kwargs.get("negative_weight", 0.5),
            settings_snapshot=settings_snapshot,
        )

    # Dual confidence with rejection strategy
    if strategy_name_lower in [
        "dual-confidence-with-rejection",
        "dual_confidence_with_rejection",
    ]:
        from .advanced_search_system.strategies.dual_confidence_with_rejection import (
            DualConfidenceWithRejectionStrategy,
        )

        return DualConfidenceWithRejectionStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 20),
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            candidate_limit=kwargs.get("candidate_limit", 100),
            evidence_threshold=kwargs.get("evidence_threshold", 0.9),
            max_search_iterations=kwargs.get("max_search_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            min_candidates_per_stage=kwargs.get("min_candidates_per_stage", 20),
            parallel_workers=kwargs.get("parallel_workers", 100),
            early_stop_threshold=kwargs.get("early_stop_threshold", 0.95),
            concurrent_evaluation=kwargs.get("concurrent_evaluation", True),
            use_llm_query_generation=kwargs.get(
                "use_llm_query_generation", True
            ),
            queries_per_combination=kwargs.get("queries_per_combination", 3),
            use_entity_seeding=kwargs.get("use_entity_seeding", True),
            use_direct_property_search=kwargs.get(
                "use_direct_property_search", True
            ),
            uncertainty_penalty=kwargs.get("uncertainty_penalty", 0.2),
            negative_weight=kwargs.get("negative_weight", 0.5),
            rejection_threshold=kwargs.get("rejection_threshold", 0.3),
            positive_threshold=kwargs.get("positive_threshold", 0.2),
            critical_constraint_rejection=kwargs.get(
                "critical_constraint_rejection", 0.2
            ),
            settings_snapshot=settings_snapshot,
        )

    # Concurrent dual confidence strategy
    if strategy_name_lower in [
        "concurrent-dual-confidence",
        "concurrent_dual_confidence",
    ]:
        from .advanced_search_system.strategies.concurrent_dual_confidence_strategy import (
            ConcurrentDualConfidenceStrategy,
        )

        return ConcurrentDualConfidenceStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 20),
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            candidate_limit=kwargs.get("candidate_limit", 100),
            evidence_threshold=kwargs.get("evidence_threshold", 0.9),
            max_search_iterations=kwargs.get("max_search_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            min_candidates_per_stage=kwargs.get("min_candidates_per_stage", 20),
            parallel_workers=kwargs.get("parallel_workers", 10),
            early_stop_threshold=kwargs.get("early_stop_threshold", 0.95),
            concurrent_evaluation=kwargs.get("concurrent_evaluation", True),
            use_llm_query_generation=kwargs.get(
                "use_llm_query_generation", True
            ),
            queries_per_combination=kwargs.get("queries_per_combination", 3),
            use_entity_seeding=kwargs.get("use_entity_seeding", True),
            use_direct_property_search=kwargs.get(
                "use_direct_property_search", True
            ),
            uncertainty_penalty=kwargs.get("uncertainty_penalty", 0.2),
            negative_weight=kwargs.get("negative_weight", 0.5),
            rejection_threshold=kwargs.get("rejection_threshold", 0.3),
            positive_threshold=kwargs.get("positive_threshold", 0.2),
            critical_constraint_rejection=kwargs.get(
                "critical_constraint_rejection", 0.2
            ),
            min_good_candidates=kwargs.get("min_good_candidates", 3),
            target_candidates=kwargs.get("target_candidates", 5),
            max_candidates=kwargs.get("max_candidates", 10),
            min_score_threshold=kwargs.get("min_score_threshold", 0.65),
            exceptional_score=kwargs.get("exceptional_score", 0.95),
            quality_plateau_threshold=kwargs.get(
                "quality_plateau_threshold", 0.1
            ),
            max_search_time=kwargs.get("max_search_time", 30.0),
            max_evaluations=kwargs.get("max_evaluations", 30),
            settings_snapshot=settings_snapshot,
        )

    # Constraint parallel strategy
    if strategy_name_lower in [
        "constraint-parallel",
        "constraint_parallel",
    ]:
        from .advanced_search_system.strategies.constraint_parallel_strategy import (
            ConstraintParallelStrategy,
        )

        return ConstraintParallelStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            max_iterations=kwargs.get("max_iterations", 20),
            confidence_threshold=kwargs.get("confidence_threshold", 0.95),
            candidate_limit=kwargs.get("candidate_limit", 100),
            evidence_threshold=kwargs.get("evidence_threshold", 0.9),
            max_search_iterations=kwargs.get("max_search_iterations", 5),
            questions_per_iteration=kwargs.get("questions_per_iteration", 3),
            min_candidates_per_stage=kwargs.get("min_candidates_per_stage", 20),
            parallel_workers=kwargs.get("parallel_workers", 100),
            early_stop_threshold=kwargs.get("early_stop_threshold", 0.95),
            concurrent_evaluation=kwargs.get("concurrent_evaluation", True),
            use_llm_query_generation=kwargs.get(
                "use_llm_query_generation", True
            ),
            queries_per_combination=kwargs.get("queries_per_combination", 3),
            use_entity_seeding=kwargs.get("use_entity_seeding", True),
            use_direct_property_search=kwargs.get(
                "use_direct_property_search", True
            ),
            uncertainty_penalty=kwargs.get("uncertainty_penalty", 0.2),
            negative_weight=kwargs.get("negative_weight", 0.5),
            rejection_threshold=kwargs.get("rejection_threshold", 0.3),
            positive_threshold=kwargs.get("positive_threshold", 0.2),
            critical_constraint_rejection=kwargs.get(
                "critical_constraint_rejection", 0.2
            ),
            settings_snapshot=settings_snapshot,
        )

    # Modular strategy
    if strategy_name_lower in ["modular", "modular-strategy"]:
        from .advanced_search_system.strategies.modular_strategy import (
            ModularStrategy,
        )

        return ModularStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            constraint_checker_type=kwargs.get(
                "constraint_checker_type", "dual_confidence"
            ),
            exploration_strategy=kwargs.get("exploration_strategy", "adaptive"),
            early_rejection=kwargs.get("early_rejection", True),
            early_stopping=kwargs.get("early_stopping", True),
            llm_constraint_processing=kwargs.get(
                "llm_constraint_processing", True
            ),
            immediate_evaluation=kwargs.get("immediate_evaluation", True),
            settings_snapshot=settings_snapshot,
        )

    # Modular parallel strategy
    if strategy_name_lower in ["modular-parallel", "modular_parallel"]:
        from .advanced_search_system.strategies.modular_strategy import (
            ModularStrategy,
        )

        return ModularStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            constraint_checker_type="dual_confidence",
            exploration_strategy="parallel",
            settings_snapshot=settings_snapshot,
        )

    # BrowseComp entity strategy
    if strategy_name_lower in ["browsecomp-entity", "browsecomp_entity"]:
        from .advanced_search_system.strategies.browsecomp_entity_strategy import (
            BrowseCompEntityStrategy,
        )

        return BrowseCompEntityStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
        )

    # Topic organization strategy
    if strategy_name_lower in [
        "topic-organization",
        "topic_organization",
        "topic",
    ]:
        from .advanced_search_system.strategies.topic_organization_strategy import (
            TopicOrganizationStrategy,
        )

        return TopicOrganizationStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            settings_snapshot=settings_snapshot,
            min_sources_per_topic=1,  # Allow single-source topics
            use_cross_engine_filter=kwargs.get("use_cross_engine_filter", True),
            filter_reorder=kwargs.get("filter_reorder", True),
            filter_reindex=kwargs.get("filter_reindex", True),
            cross_engine_max_results=kwargs.get(  # type: ignore[arg-type]
                "cross_engine_max_results", None
            ),
            search_original_query=kwargs.get("search_original_query", True),
            max_topics=kwargs.get("max_topics", 5),
            similarity_threshold=kwargs.get("similarity_threshold", 0.3),
            use_focused_iteration=kwargs.get("use_focused_iteration", False),
            enable_refinement=kwargs.get(
                "enable_refinement", False
            ),  # Disable refinement iterations for now
            max_refinement_iterations=kwargs.get(
                "max_refinement_iterations",
                1,  # Set to 1 iteration for faster results
            ),
            generate_text=kwargs.get("generate_text", True),
        )

    # Iterative refinement strategy
    if strategy_name_lower in [
        "iterative-refinement",
        "iterative_refinement",
    ]:
        from .advanced_search_system.strategies.iterative_refinement_strategy import (
            IterativeRefinementStrategy,
        )

        # Get the initial strategy to use (default to source-based)
        initial_strategy_name = kwargs.get("initial_strategy", "source-based")

        # Create the initial strategy
        initial_strategy = create_strategy(
            strategy_name=initial_strategy_name,
            model=model,
            search=search,
            all_links_of_system=[],  # Fresh list for initial strategy
            settings_snapshot=settings_snapshot,
            search_original_query=kwargs.get("search_original_query", True),
        )

        return IterativeRefinementStrategy(
            model=model,
            search=search,
            initial_strategy=initial_strategy,
            all_links_of_system=all_links_of_system,
            settings_snapshot=settings_snapshot,
            evaluation_frequency=kwargs.get("evaluation_frequency", 1),
            max_refinements=kwargs.get("max_refinements", 3),
            confidence_threshold=kwargs.get(
                "confidence_threshold", 0.95
            ),  # Increased from 0.8
        )

    # Standard strategy
    if strategy_name_lower == "standard":
        from .advanced_search_system.strategies.standard_strategy import (
            StandardSearchStrategy,
        )

        return StandardSearchStrategy(
            model=model,
            search=search,
            all_links_of_system=all_links_of_system,
            settings_snapshot=settings_snapshot,
        )

    # MCP strategy (ReAct pattern - agentic research)
    if strategy_name_lower in ["mcp", "agentic"]:
        from .advanced_search_system.strategies.mcp_strategy import (
            MCPSearchStrategy,
        )

        # Get MCP server configurations from settings
        mcp_servers = kwargs.get(
            "mcp_servers",
            _get_setting(settings_snapshot, "mcp.servers", []),
        )

        return MCPSearchStrategy(
            model=model,
            search=search,
            mcp_servers=mcp_servers,
            max_iterations=kwargs.get("max_iterations", 10),
            include_web_search=kwargs.get("include_web_search", True),
            all_links_of_system=all_links_of_system,
            settings_snapshot=settings_snapshot,
        )

    # LangGraph agent strategy (parallel subagent research)
    if strategy_name_lower in ["langgraph-agent", "langgraph_agent"]:
        from .advanced_search_system.strategies.langgraph_agent_strategy import (
            LangGraphAgentStrategy,
        )

        return LangGraphAgentStrategy(
            model=model,
            search=search,
            max_iterations=kwargs.get("max_iterations", 15),
            max_sub_iterations=kwargs.get("max_sub_iterations", 8),
            include_sub_research=kwargs.get("include_sub_research", True),
            all_links_of_system=all_links_of_system,
            settings_snapshot=settings_snapshot,
        )

    # Default to source-based if unknown
    logger.warning(
        f"Unknown strategy: {strategy_name}, defaulting to source-based"
    )
    from .advanced_search_system.strategies.source_based_strategy import (
        SourceBasedSearchStrategy,
    )

    return SourceBasedSearchStrategy(
        model=model,
        search=search,
        include_text_content=True,
        use_cross_engine_filter=True,
        all_links_of_system=all_links_of_system,
        use_atomic_facts=False,
        settings_snapshot=settings_snapshot,
        search_original_query=kwargs.get("search_original_query", True),
    )
