"""Smart tool selection — filter tools by task-type relevance."""
from __future__ import annotations

import re


def _tokenize(text: str) -> set[str]:
    """Split text into lowercase word tokens."""
    return set(re.findall(r"[a-zA-Z\u0400-\u04FF]{2,}", text.lower()))


def _score_tool(schema: dict, hint_tokens: set[str]) -> float:
    """Score a tool's relevance to the task hint (0.0 - 1.0)."""
    text = f"{schema.get('name', '')} {schema.get('description', '')}"
    tool_tokens = _tokenize(text)
    if not tool_tokens or not hint_tokens:
        return 0.0
    overlap = tool_tokens & hint_tokens
    return len(overlap) / max(len(hint_tokens), 1)


def select_relevant_tools(
    schemas: list[dict] | None,
    *,
    task_hint: str | None,
    mandatory: set[str] | None = None,
    min_tools: int = 3,
    threshold: float = 0.1,
) -> list[dict] | None:
    """Select tools relevant to a task hint.

    Args:
        schemas: Full list of tool schemas.
        task_hint: Natural-language description of the current task.
        mandatory: Tool names that must always be included.
        min_tools: Minimum number of tools to return (prevents over-filtering).
        threshold: Minimum relevance score to include a tool.

    Returns:
        Filtered list preserving original order, or all tools if no hint.
    """
    if schemas is None:
        return None
    if not schemas:
        return []
    if not task_hint:
        return list(schemas)

    mandatory = mandatory or set()
    hint_tokens = _tokenize(task_hint)
    if not hint_tokens:
        return list(schemas)

    scored: list[tuple[float, int, dict]] = []
    for idx, schema in enumerate(schemas):
        name = schema.get("name", "")
        if name in mandatory:
            scored.append((999.0, idx, schema))
        else:
            score = _score_tool(schema, hint_tokens)
            scored.append((score, idx, schema))

    scored.sort(key=lambda x: (-x[0], x[1]))

    selected: list[tuple[int, dict]] = []
    for score, idx, schema in scored:
        if score >= threshold or len(selected) < min_tools:
            selected.append((idx, schema))

    selected.sort(key=lambda x: x[0])
    return [schema for _, schema in selected]
