# #region AssistantLlmPlanner [C:5] [TYPE Module] [SEMANTICS assistant, llm, planner, tool, catalog]
# @BRIEF LLM-based intent planning, tool catalog construction, and authorization for the assistant API.
# @LAYER API
# @RELATION DEPENDS_ON -> [AssistantSchemas]
# @RELATION DEPENDS_ON -> [AssistantResolvers]
# @RELATION DISPATCHES -> [AssistantLlmPlannerIntent]
# @PRE  Assistant routes initialized, user authenticated
# @POST  LLM tool catalog filtered and returned
# @INVARIANT  Tool catalog is filtered by user permissions before being sent to LLM.
# @SIDE_EFFECT  Filters tool catalog by user permissions
# @DATA_CONTRACT  UserPermissions -> ToolCatalog

from __future__ import annotations

from typing import Any

from sqlalchemy.orm import Session

from src.core.config_manager import ConfigManager
from src.schemas.auth import User

from ._tool_registry import (
    _check_any_permission,
    _has_any_permission,
    get_catalog,
)


# #region _build_tool_catalog [C:2] [TYPE Function]
# @BRIEF Build tool catalog from the central registry, appending dataset-review tools when a session is active.
# @PRE  current_user is authenticated; config/db are available.
# @POST  Returns list of executable tools filtered by permission and runtime availability.
def _build_tool_catalog(
    current_user: User,
    config_manager: ConfigManager,
    db: Session,
    dataset_review_context: dict[str, Any] | None = None,
) -> list[dict[str, Any]]:
    """Build tool catalog from the central registry, with optional dataset-review tools."""
    available = get_catalog(current_user, config_manager, db)

    # Dataset review tools are session-scoped — only available when a review is active.
    if dataset_review_context is not None:
        from ._schemas import INTENT_PERMISSION_CHECKS

        dataset_tools: list[dict[str, Any]] = [
            {
                "operation": "dataset_review_answer_context",
                "domain": "dataset_review",
                "description": "Answer questions using the currently bound dataset review session context",
                "required_entities": ["dataset_review_session_id"],
                "optional_entities": [],
                "risk_level": "safe",
                "requires_confirmation": False,
            },
            {
                "operation": "dataset_review_approve_mappings",
                "domain": "dataset_review",
                "description": "Approve warning-sensitive execution mappings in the current dataset review session",
                "required_entities": ["dataset_review_session_id", "session_version"],
                "optional_entities": ["mapping_ids"],
                "risk_level": "guarded",
                "requires_confirmation": True,
            },
            {
                "operation": "dataset_review_set_field_semantics",
                "domain": "dataset_review",
                "description": "Apply explicit semantic field override or candidate selection in the current dataset review session",
                "required_entities": [
                    "dataset_review_session_id",
                    "session_version",
                    "field_id",
                ],
                "optional_entities": [
                    "candidate_id",
                    "verbose_name",
                    "description",
                    "display_format",
                    "lock_field",
                ],
                "risk_level": "guarded",
                "requires_confirmation": True,
            },
            {
                "operation": "dataset_review_generate_sql_preview",
                "domain": "dataset_review",
                "description": "Generate a Superset-compiled SQL preview for the current dataset review session",
                "required_entities": ["dataset_review_session_id", "session_version"],
                "optional_entities": [],
                "risk_level": "guarded",
                "requires_confirmation": True,
            },
        ]
        for tool in dataset_tools:
            checks = INTENT_PERMISSION_CHECKS.get(tool["operation"], [])
            if checks and not _has_any_permission(current_user, checks):
                continue
            available.append(tool)
    return available


# #endregion _build_tool_catalog


# #region _coerce_intent_entities [C:2] [TYPE Function]
# @BRIEF Normalize intent entity value types from LLM output to route-compatible values.
# @PRE  intent contains entities dict or missing entities.
# @POST  Returned intent has numeric ids coerced where possible and string values stripped.
def _coerce_intent_entities(intent: dict[str, Any]) -> dict[str, Any]:
    entities = intent.get("entities")
    if not isinstance(entities, dict):
        intent["entities"] = {}
        entities = intent["entities"]
    for key in ("dashboard_id", "dataset_id"):
        value = entities.get(key)
        if isinstance(value, str) and value.strip().isdigit():
            entities[key] = int(value.strip())
    for key, value in list(entities.items()):
        if isinstance(value, str):
            entities[key] = value.strip()
    return intent


# #endregion _coerce_intent_entities


# #endregion AssistantLlmPlanner
