"""Search functions for RAG retrieval."""

import logging
from typing import Any

from .store import RAGStore, get_store

logger = logging.getLogger(__name__)


async def search_examples(
    query: str,
    limit: int = 5,
    store: RAGStore | None = None,
) -> list[dict[str, Any]]:
    """Search for scene examples matching a query.

    Args:
        query: Natural language description of what you want to animate
        limit: Maximum number of results
        store: RAG store instance

    Returns:
        List of matching examples with code
    """
    store = store or get_store()

    if not store.table_exists(store.EXAMPLES_TABLE):
        return [{"error": "Examples not indexed. Run index_manimgl first."}]

    results = store.search(store.EXAMPLES_TABLE, query, limit=limit)

    return [
        {
            "name": r.get("name"),
            "code": r.get("code"),
            "source": r.get("source"),
            "animations_used": r.get("animations", []),
            "mobjects_used": r.get("mobjects", []),
            "relevance": 1 - r.get("_distance", 1),
        }
        for r in results
    ]


async def search_api(
    query: str,
    category: str | None = None,
    limit: int = 10,
    store: RAGStore | None = None,
) -> list[dict[str, Any]]:
    """Search for API signatures.

    Args:
        query: What you're looking for (class name, functionality, etc.)
        category: Filter by category (animation, mobject, scene, util)
        limit: Maximum number of results
        store: RAG store instance

    Returns:
        List of matching API signatures
    """
    store = store or get_store()

    if not store.table_exists(store.API_TABLE):
        return [{"error": "API not indexed. Run index_manimgl first."}]

    filter_expr = f"category = '{category}'" if category else None
    results = store.search(store.API_TABLE, query, limit=limit, filter_expr=filter_expr)

    return [
        {
            "name": r.get("name"),
            "signature": r.get("signature"),
            "module": r.get("module"),
            "category": r.get("category"),
            "docstring": r.get("docstring"),
            "relevance": 1 - r.get("_distance", 1),
        }
        for r in results
    ]


async def search_patterns(
    query: str,
    category: str | None = None,
    limit: int = 5,
    store: RAGStore | None = None,
) -> list[dict[str, Any]]:
    """Search for animation pattern templates.

    Args:
        query: What kind of animation you want (e.g., "riemann sum", "matrix transform")
        category: Filter by category (calculus, linear_algebra, physics, etc.)
        limit: Maximum number of results
        store: RAG store instance

    Returns:
        List of matching patterns with code templates
    """
    store = store or get_store()

    if not store.table_exists(store.PATTERNS_TABLE):
        return [{"error": "Patterns not indexed. Run index_manimgl first."}]

    filter_expr = f"category = '{category}'" if category else None
    results = store.search(store.PATTERNS_TABLE, query, limit=limit, filter_expr=filter_expr)

    return [
        {
            "name": r.get("name"),
            "description": r.get("description"),
            "code": r.get("code"),
            "category": r.get("category"),
            "tags": r.get("tags", []),
            "relevance": 1 - r.get("_distance", 1),
        }
        for r in results
    ]


async def validate_api_call(
    class_name: str,
    parameters: dict[str, Any],
    store: RAGStore | None = None,
) -> dict[str, Any]:
    """Validate an API call against indexed signatures.

    Args:
        class_name: Name of the class being instantiated
        parameters: Parameters being passed
        store: RAG store instance

    Returns:
        Validation result with any issues found
    """
    store = store or get_store()

    if not store.table_exists(store.API_TABLE):
        return {"valid": True, "warning": "API not indexed, validation skipped"}

    # Search for exact class name
    results = store.search(store.API_TABLE, class_name, limit=5)

    # Find exact match
    exact_match = None
    for r in results:
        if r.get("name") == class_name:
            exact_match = r
            break

    if not exact_match:
        return {
            "valid": True,
            "warning": f"Class '{class_name}' not found in index",
            "suggestions": [r.get("name") for r in results[:3]],
        }

    # Parse stored parameters
    try:
        stored_params = eval(exact_match.get("parameters", "[]"))
    except Exception:
        stored_params = []

    param_names = {p["name"] for p in stored_params if p["name"] != "self"}

    # Check for unknown parameters
    unknown = set(parameters.keys()) - param_names - {"self"}

    if unknown:
        return {
            "valid": False,
            "error": f"Unknown parameters: {', '.join(unknown)}",
            "valid_parameters": list(param_names),
            "signature": exact_match.get("signature"),
        }

    return {
        "valid": True,
        "signature": exact_match.get("signature"),
        "docstring": exact_match.get("docstring"),
    }


async def get_similar_errors(
    error_message: str,
    limit: int = 3,
    store: RAGStore | None = None,
) -> list[dict[str, Any]]:
    """Find similar errors and their fixes.

    Args:
        error_message: The error message encountered
        limit: Maximum number of results
        store: RAG store instance

    Returns:
        List of similar errors with fixes
    """
    store = store or get_store()

    if not store.table_exists(store.ERRORS_TABLE):
        return []

    results = store.search(store.ERRORS_TABLE, error_message, limit=limit)

    return [
        {
            "error_pattern": r.get("pattern"),
            "fix": r.get("fix"),
            "example": r.get("example"),
            "relevance": 1 - r.get("_distance", 1),
        }
        for r in results
    ]


async def store_error_fix(
    error_pattern: str,
    fix: str,
    example: str | None = None,
    store: RAGStore | None = None,
) -> dict[str, Any]:
    """Store an error pattern and its fix for future reference.

    Args:
        error_pattern: The error message pattern
        fix: How to fix this error
        example: Optional code example of the fix
        store: RAG store instance

    Returns:
        Confirmation of storage
    """
    store = store or get_store()

    text = f"Error: {error_pattern}\nFix: {fix}"
    data = [
        {
            "vector": store.embed_single(text),
            "text": text,
            "pattern": error_pattern,
            "fix": fix,
            "example": example or "",
        }
    ]

    if store.table_exists(store.ERRORS_TABLE):
        store.add_to_table(store.ERRORS_TABLE, data)
    else:
        store.create_table(store.ERRORS_TABLE, data)

    return {"success": True, "pattern": error_pattern}
