"""MCP tool for querying cached form components selectively.

Provides form_query — a lightweight alternative to form_get that returns
only matching components from the local SQLite JSON1 cache.
"""

from __future__ import annotations

from typing import Any

from mcp.server.fastmcp.exceptions import ToolError

from mcp_eregistrations_bpa.bpa_client.errors import BPAClientError, translate_error
from mcp_eregistrations_bpa.config import resolve_db_path
from mcp_eregistrations_bpa.db.form_cache import query_form_components
from mcp_eregistrations_bpa.tools.forms import FORM_TYPES, _fetch_and_cache_form

__all__ = ["form_query", "register_form_cache_tools"]


async def form_query(
    service_id: str | int,
    form_type: str = "applicant",
    component_key: str | None = None,
    component_type: str | None = None,
    required_only: bool = False,
    has_determinants: bool = False,
    search_label: str | None = None,
    path_prefix: str | None = None,
    visible_only: bool = False,
    instance: str | None = None,
) -> dict[str, Any]:
    """Query form components selectively from local cache.

    Returns matching components without loading the full form schema.
    Auto-populates cache on first access (transparent to caller).

    Args:
        service_id: BPA service UUID.
        form_type: "applicant" (default), "guide", "send_file", "payment".
        component_key: Get specific component by key.
        component_type: Filter by type (textfield, select, panel, etc.).
        required_only: Only required components (default: False).
        has_determinants: Only components with determinants (default: False).
        search_label: Case-insensitive label search.
        path_prefix: Components inside a parent key path.
        visible_only: Exclude hidden components and children of hidden
            containers (default: False).
        instance: Profile name to target.

    Returns:
        dict with service_id, form_type, query, components, total, cached.
    """
    if form_type not in FORM_TYPES:
        valid_types = ", ".join(sorted(FORM_TYPES.keys()))
        raise ToolError(f"Invalid form type '{form_type}'. Valid types: {valid_types}")

    sid = str(service_id)
    db_path = resolve_db_path(instance)

    # Try cache first
    components = await query_form_components(
        sid,
        form_type,
        db_path,
        component_key=component_key,
        component_type=component_type,
        required_only=required_only,
        has_determinants=has_determinants,
        search_label=search_label,
        path_prefix=path_prefix,
        visible_only=visible_only,
    )

    cached = True
    if components is None:
        # Cache miss — fetch from BPA and populate cache
        cached = False
        try:
            await _fetch_and_cache_form(service_id, form_type, instance)
        except ToolError:
            raise
        except BPAClientError as e:
            raise translate_error(e, resource_type="form", resource_id=service_id)

        # Retry query after cache population
        components = await query_form_components(
            sid,
            form_type,
            db_path,
            component_key=component_key,
            component_type=component_type,
            required_only=required_only,
            has_determinants=has_determinants,
            search_label=search_label,
            path_prefix=path_prefix,
            visible_only=visible_only,
        )
        if components is None:
            components = []

    # Build query description for the response
    query_parts: list[str] = []
    if component_key:
        query_parts.append(f"key={component_key}")
    if component_type:
        query_parts.append(f"type={component_type}")
    if required_only:
        query_parts.append("required_only")
    if has_determinants:
        query_parts.append("has_determinants")
    if search_label:
        query_parts.append(f"label~{search_label}")
    if path_prefix:
        query_parts.append(f"path={path_prefix}")
    if visible_only:
        query_parts.append("visible_only")

    return {
        "service_id": sid,
        "form_type": form_type,
        "query": ", ".join(query_parts) if query_parts else "all",
        "components": components,
        "total": len(components),
        "cached": cached,
    }


def register_form_cache_tools(mcp: Any) -> None:
    """Register form cache tools with the MCP server."""
    from mcp_eregistrations_bpa.tools.annotations import READ

    mcp.tool(annotations=READ)(form_query)
