"""Helper functions for advanced context strategies Robot Framework tests."""

from __future__ import annotations

import sys
from pathlib import Path
from typing import Any

# Robot Framework adds the library file's directory (robot/) to sys.path, but
# features.mocks lives at the project root. Insert the project root so the
# import below resolves correctly regardless of invocation context.
_PROJECT_ROOT = str(Path(__file__).resolve().parents[1])
if _PROJECT_ROOT not in sys.path:
    sys.path.insert(0, _PROJECT_ROOT)

from features.mocks.advanced_context_strategies_mocks import (  # noqa: E402
    AdaptiveContextSelector,
    ContextFusionStrategy,
    RelevanceScoringStrategy,
)

from cleveragents.application.services.context_strategies import (  # noqa: E402
    BreadthDepthNavigatorStrategy,
    SemanticEmbeddingStrategy,
)
from cleveragents.domain.models.core.context_fragment import (  # noqa: E402
    ContextBudget,
    ContextFragment,
    FragmentProvenance,
)

# Default provenance used for test fragments (no real resource needed).
_TEST_PROVENANCE = FragmentProvenance(resource_uri="test://fixture")


def create_semantic_search_strategy_impl() -> SemanticEmbeddingStrategy:
    """Create a semantic search strategy with FakeEmbeddings."""
    return SemanticEmbeddingStrategy(min_similarity=0.05)


def create_relevance_scoring_strategy_impl() -> RelevanceScoringStrategy:
    """Create a relevance scoring strategy."""
    return RelevanceScoringStrategy()


def create_adaptive_selector_impl() -> AdaptiveContextSelector:
    """Create an adaptive context strategy selector."""
    return AdaptiveContextSelector()


def create_context_fusion_strategy_impl(
    strategies: list[str],
) -> ContextFusionStrategy:
    """Create a context fusion strategy."""
    return ContextFusionStrategy(strategies)


def create_test_fragments_impl(args: list[str]) -> list[ContextFragment]:
    """Create test context fragments from arguments."""
    fragments: list[ContextFragment] = []
    i = 0
    while i < len(args):
        if i + 4 < len(args):
            uko_node = args[i]
            content = args[i + 1]
            score = float(args[i + 2])
            tokens = int(args[i + 3])
            depth = int(args[i + 4])

            frag = ContextFragment(
                uko_node=uko_node,
                content=content,
                relevance_score=score,
                token_count=tokens,
                detail_depth=depth,
                provenance=_TEST_PROVENANCE,
            )
            fragments.append(frag)
            i += 5
        else:
            break

    return fragments


def create_context_budget_impl(max_tokens: int, reserved_tokens: int) -> ContextBudget:
    """Create a context budget."""
    return ContextBudget(
        max_tokens=int(max_tokens),
        reserved_tokens=int(reserved_tokens),
    )


def search_with_query_impl(
    strategy: SemanticEmbeddingStrategy,
    query: str,
    fragments: list[ContextFragment],
    budget: ContextBudget,
) -> list[ContextFragment]:
    """Search with a query."""
    strategy.set_query(query)
    return strategy.assemble(fragments, budget)


def assemble_with_strategy_impl(
    strategy: Any,
    fragments: list[ContextFragment],
    budget: ContextBudget,
) -> list[ContextFragment]:
    """Assemble with a strategy."""
    return strategy.assemble(fragments, budget)


def select_strategy_for_query_impl(
    selector: AdaptiveContextSelector, query: str
) -> str:
    """Select strategy for a query."""
    request = {"query": query}
    strategy_name, _ = selector.select_strategy(request)
    return strategy_name


def select_strategy_without_query_impl(selector: AdaptiveContextSelector) -> str:
    """Select strategy without query."""
    request = {}
    strategy_name, _ = selector.select_strategy(request)
    return strategy_name


def select_strategy_with_invalid_request_impl(
    selector: AdaptiveContextSelector,
) -> str:
    """Select strategy with invalid request."""
    request = {"invalid": "data"}
    strategy_name, _ = selector.select_strategy(request)
    return strategy_name


def fuse_with_query_impl(
    fusion: ContextFusionStrategy,
    query: str,
    fragments: list[ContextFragment],
    budget: ContextBudget,
) -> list[ContextFragment]:
    """Fuse strategies with a query."""
    return fusion.assemble(fragments, budget, query)


def load_strategy_from_yaml_impl(config: dict[str, Any]) -> Any:
    """Load strategy from YAML configuration."""
    strategy_type = config.get("strategy")

    if strategy_type == "semantic-embedding":
        min_sim = config.get("min_similarity", 0.05)
        return SemanticEmbeddingStrategy(min_similarity=min_sim)
    elif strategy_type == "relevance-scoring":
        return RelevanceScoringStrategy()
    elif strategy_type == "adaptive-selector":
        return AdaptiveContextSelector()
    elif strategy_type == "context-fusion":
        strategies = config.get("strategies", [])
        return ContextFusionStrategy(strategies)
    else:
        raise ValueError(f"Unknown strategy type: {strategy_type!r}")


def create_context_assembler_with_advanced_strategies_impl() -> dict[str, Any]:
    """Create a ContextAssembler with advanced strategies."""
    return {
        "strategies": [
            SemanticEmbeddingStrategy(),
            RelevanceScoringStrategy(),
            BreadthDepthNavigatorStrategy(),
        ]
    }


def create_context_assembler_with_multiple_strategies_impl() -> dict[str, Any]:
    """Create a ContextAssembler with multiple strategies."""
    return {
        "strategies": [
            SemanticEmbeddingStrategy(),
            RelevanceScoringStrategy(),
        ]
    }


def assemble_context_with_query_impl(
    assembler: dict[str, Any],
    query: str,
    fragments: list[ContextFragment],
    budget: ContextBudget,
) -> list[ContextFragment]:
    """Assemble context with a query."""
    request = {"query": query}

    best_strategy = None
    best_confidence = 0.0

    for strategy in assembler["strategies"]:
        confidence = strategy.can_handle(request)
        if confidence > best_confidence:
            best_confidence = confidence
            best_strategy = strategy

    if best_strategy is None:
        best_strategy = assembler["strategies"][0]

    if hasattr(best_strategy, "set_query"):
        best_strategy.set_query(query)

    return best_strategy.assemble(fragments, budget)


def get_uko_nodes_impl(fragments: list[ContextFragment]) -> list[str]:
    """Extract uko_node values from fragments."""
    return [f.uko_node for f in fragments]
