"""Tool definitions for CorpusDB methods.

CORPUS_TOOLS: OpenAI function-calling format.
CORPUS_TOOLS_ANTHROPIC: Anthropic tool-use format (auto-generated).
"""

from __future__ import annotations

from typing import Any

CORPUS_TOOLS: list[dict[str, Any]] = [
    {
        "type": "function",
        "function": {
            "name": "get_corpus_summary",
            "description": "Get a summary of the corpus: total files, segments, vocabulary size, signer count, and tier count.",
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "search_glosses",
            "description": "Full-text search for glosses (sign labels) in the corpus. Returns matching segments with file/tier info.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "Search query (supports prefix matching, e.g. 'HELLO*')",
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Maximum results to return (default 100)",
                        "default": 100,
                    },
                },
                "required": ["query"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_top_glosses",
            "description": "Get the most frequent glosses (signs) in the corpus, ranked by frequency.",
            "parameters": {
                "type": "object",
                "properties": {
                    "limit": {
                        "type": "integer",
                        "description": "Number of top glosses to return (default 50)",
                        "default": 50,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_gloss_occurrences",
            "description": "Get all occurrences of a specific gloss in the corpus, with timing, file, and signer info.",
            "parameters": {
                "type": "object",
                "properties": {
                    "gloss": {
                        "type": "string",
                        "description": "The gloss (sign label) to find, e.g. 'HELLO'",
                    },
                    "signer_id": {
                        "type": "string",
                        "description": "Optional: filter to a specific signer/participant",
                    },
                },
                "required": ["gloss"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_gloss_duration_stats",
            "description": "Get duration statistics (mean, std, min, max, median in milliseconds) for a specific gloss.",
            "parameters": {
                "type": "object",
                "properties": {
                    "gloss": {
                        "type": "string",
                        "description": "The gloss to analyze",
                    },
                    "signer_id": {
                        "type": "string",
                        "description": "Optional: filter to a specific signer",
                    },
                },
                "required": ["gloss"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "compare_signer_durations",
            "description": "Compare how long different signers produce a specific gloss. Returns per-signer duration stats.",
            "parameters": {
                "type": "object",
                "properties": {
                    "gloss": {
                        "type": "string",
                        "description": "The gloss to compare across signers",
                    },
                },
                "required": ["gloss"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_concordance",
            "description": "Get KWIC (Key Word In Context) concordance view for a target gloss, showing surrounding signs.",
            "parameters": {
                "type": "object",
                "properties": {
                    "target": {
                        "type": "string",
                        "description": "The target gloss to find in context",
                    },
                    "window": {
                        "type": "integer",
                        "description": "Number of surrounding signs to include (default 5)",
                        "default": 5,
                    },
                },
                "required": ["target"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_ngrams",
            "description": "Get the most frequent n-gram (sign sequences) in the corpus.",
            "parameters": {
                "type": "object",
                "properties": {
                    "n": {
                        "type": "integer",
                        "description": "N-gram size (2=bigrams, 3=trigrams, etc.)",
                        "default": 2,
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Maximum n-grams to return (default 50)",
                        "default": 50,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_cooccurrence",
            "description": "Find which signs co-occur most frequently with a target gloss within a window.",
            "parameters": {
                "type": "object",
                "properties": {
                    "target": {
                        "type": "string",
                        "description": "The target gloss",
                    },
                    "window": {
                        "type": "integer",
                        "description": "Window size around the target (default 3)",
                        "default": 3,
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Maximum results (default 50)",
                        "default": 50,
                    },
                },
                "required": ["target"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_vocabulary_stats",
            "description": "Get vocabulary statistics: size, total tokens, and frequency distribution of glosses.",
            "parameters": {
                "type": "object",
                "properties": {
                    "limit": {
                        "type": "integer",
                        "description": "Max glosses in frequency list (default 500)",
                        "default": 500,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_lexical_richness",
            "description": "Compute lexical richness metrics: TTR, hapax legomena, Yule's K, Simpson's D, Brunet's W, Honore's R, MATTR.",
            "parameters": {
                "type": "object",
                "properties": {
                    "mattr_window": {
                        "type": "integer",
                        "description": "Window size for MATTR calculation (default 50)",
                        "default": 50,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_transitions",
            "description": "Get bigram transition probabilities between signs, with entropy and predictability scores.",
            "parameters": {
                "type": "object",
                "properties": {
                    "top_n": {
                        "type": "integer",
                        "description": "Number of top signs to include (default 30)",
                        "default": 30,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_fluency_stats",
            "description": "Get per-file signing rate, pause analysis, and duration vs frequency data.",
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_per_signer_fluency",
            "description": "Compare signing rate (signs/min), average sign duration, and pause patterns across signers.",
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_dashboard_stats",
            "description": "Get comprehensive dashboard statistics: files, segments, vocabulary, hapax, dis legomena counts.",
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_frequency_distribution",
            "description": "Get ranked Zipf-curve frequency distribution of all glosses.",
            "parameters": {
                "type": "object",
                "properties": {
                    "limit": {
                        "type": "integer",
                        "description": "Maximum glosses to return (default 500)",
                        "default": 500,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_duration_histogram",
            "description": "Get a binned histogram of sign durations in the corpus.",
            "parameters": {
                "type": "object",
                "properties": {
                    "bins": {
                        "type": "integer",
                        "description": "Number of histogram bins (default 30)",
                        "default": 30,
                    },
                    "max_ms": {
                        "type": "integer",
                        "description": "Maximum duration in ms to include (default 3000)",
                        "default": 3000,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_all_duration_stats",
            "description": "Get per-gloss duration aggregates (mean, std, min, max, median) for the most frequent glosses.",
            "parameters": {
                "type": "object",
                "properties": {
                    "limit": {
                        "type": "integer",
                        "description": "Maximum glosses to return (default 50)",
                        "default": 50,
                    },
                    "min_count": {
                        "type": "integer",
                        "description": "Minimum occurrences to include (default 5)",
                        "default": 5,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_minimal_pairs",
            "description": "Find glosses that are similar in form (near-minimal pairs based on string similarity).",
            "parameters": {
                "type": "object",
                "properties": {
                    "threshold": {
                        "type": "number",
                        "description": "Similarity threshold 0-1 (default 0.7)",
                        "default": 0.7,
                    },
                    "max_pairs": {
                        "type": "integer",
                        "description": "Maximum pairs to return (default 50)",
                        "default": 50,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_cooccurrence_matrix",
            "description": "Get the full co-occurrence matrix for the top N glosses.",
            "parameters": {
                "type": "object",
                "properties": {
                    "top_n": {
                        "type": "integer",
                        "description": "Number of top glosses to include (default 30)",
                        "default": 30,
                    },
                    "window": {
                        "type": "integer",
                        "description": "Window size for co-occurrence (default 2)",
                        "default": 2,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_per_signer_richness",
            "description": "Get per-signer lexical diversity metrics: TTR, vocabulary size, MATTR, Yule's K.",
            "parameters": {
                "type": "object",
                "properties": {
                    "mattr_window": {
                        "type": "integer",
                        "description": "Window size for MATTR (default 50)",
                        "default": 50,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_corpus_status",
            "description": "Get DB status: file count, segment count, and last updated timestamp.",
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_file_list",
            "description": "List all files in the corpus with their segment counts.",
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "compare_cross_workspace",
            "description": "Compare a gloss across two or more workspaces. Returns occurrences from each workspace for side-by-side video comparison.",
            "parameters": {
                "type": "object",
                "properties": {
                    "gloss": {
                        "type": "string",
                        "description": "The gloss to compare across workspaces",
                    },
                    "workspaces": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "Workspace names to compare (2-4)",
                    },
                    "limit_per_workspace": {
                        "type": "integer",
                        "description": "Max occurrences per workspace (default 5)",
                        "default": 5,
                    },
                },
                "required": ["gloss", "workspaces"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_group_comparison",
            "description": (
                "Compare linguistic metrics (tokens, vocabulary size, TTR, avg duration) "
                "across groups of signers or metadata values. Use group_by='participant' "
                "to compare signers, or group_by='metadata' with a metadata_key to compare "
                "by extracted file metadata (e.g. region, age group)."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "group_by": {
                        "type": "string",
                        "enum": ["participant", "metadata"],
                        "description": "Group by signer (participant) or metadata field",
                    },
                    "metadata_key": {
                        "type": "string",
                        "description": "Required when group_by='metadata': the metadata key to group by",
                    },
                },
                "required": ["group_by"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_top_glosses_for_group",
            "description": (
                "Get the most frequent glosses for a specific group (signer or metadata value). "
                "Use after get_group_comparison to drill into a specific group."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "group_by": {
                        "type": "string",
                        "enum": ["participant", "metadata"],
                        "description": "Same grouping as the comparison",
                    },
                    "group_value": {
                        "type": "string",
                        "description": "The specific group value (signer ID or metadata value)",
                    },
                    "metadata_key": {
                        "type": "string",
                        "description": "Required when group_by='metadata'",
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Max glosses to return (default 30)",
                        "default": 30,
                    },
                },
                "required": ["group_by", "group_value"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_hand_comparison",
            "description": (
                "Compare left hand vs right hand signing. Returns per-hand statistics "
                "(tokens, vocabulary, duration), vocabulary overlap, and simultaneous "
                "signs (signs produced on both hands at the same time). Requires tier "
                "roles to be assigned (left_hand and right_hand)."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "top_n": {
                        "type": "integer",
                        "description": "Number of top vocabulary items per hand (default 50)",
                        "default": 50,
                    },
                },
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_tier_roles",
            "description": (
                "List all tier role assignments. Tier roles map ELAN tier names to "
                "semantic roles like 'gloss', 'left_hand', 'right_hand', 'translation', "
                "'boundary', 'ignore'. Returns a dict of {tier_pattern: role}."
            ),
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_metadata_keys",
            "description": (
                "List all metadata keys that have been extracted from file paths. "
                "Returns keys with their file counts. Metadata is extracted using "
                "the path segment extractor on the workspace page."
            ),
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_metadata_values",
            "description": "Get all distinct values for a given metadata key, with file counts.",
            "parameters": {
                "type": "object",
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "The metadata key to look up values for",
                    },
                },
                "required": ["key"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_signers_per_file",
            "description": "Get a mapping of file names to their signer/participant IDs.",
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "universal_search",
            "description": (
                "Search across the entire corpus for files, glosses, signers, and metadata "
                "values matching a query string. Returns categorized results."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "Search query string",
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Max results per category (default 20)",
                        "default": 20,
                    },
                },
                "required": ["query"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "run_sql_query",
            "description": (
                "Execute a read-only SQL query against the corpus database. "
                "Use this for any analytical question that isn't covered by the "
                "other tools, or when you need full control over filtering, "
                "grouping, and aggregation. Only SELECT statements are allowed."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "sql": {
                        "type": "string",
                        "description": "A SELECT SQL query to execute against the corpus database",
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Maximum rows to return (default 500)",
                        "default": 500,
                    },
                },
                "required": ["sql"],
            },
        },
    },
]


def _openai_to_anthropic(tools: list[dict[str, Any]]) -> list[dict[str, Any]]:
    """Convert OpenAI tool definitions to Anthropic format."""
    result = []
    for tool in tools:
        fn = tool["function"]
        result.append(
            {
                "name": fn["name"],
                "description": fn["description"],
                "input_schema": fn["parameters"],
            }
        )
    return result


CORPUS_TOOLS_ANTHROPIC = _openai_to_anthropic(CORPUS_TOOLS)


# ---------------------------------------------------------------------------
# Workspace-aware tools (added dynamically when multiple workspaces exist)
# ---------------------------------------------------------------------------

_WORKSPACE_TOOLS_OPENAI: list[dict] = [
    {
        "type": "function",
        "function": {
            "name": "list_workspaces",
            "description": (
                "List all available workspaces (corpora) with summary statistics. "
                "Each workspace is a separate corpus with its own ELAN files."
            ),
            "parameters": {"type": "object", "properties": {}, "required": []},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "query_other_workspace",
            "description": (
                "Run any corpus tool against a different workspace (corpus). "
                "Use this to compare data across corpora or look up glosses "
                "in a workspace that is not the currently active one."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "workspace": {
                        "type": "string",
                        "description": "Name of the workspace to query",
                    },
                    "tool_name": {
                        "type": "string",
                        "description": (
                            "The corpus tool to run (e.g. 'get_corpus_summary', "
                            "'search_glosses', 'get_top_glosses', etc.)"
                        ),
                    },
                    "tool_args": {
                        "type": "object",
                        "description": "Arguments to pass to the tool",
                    },
                },
                "required": ["workspace", "tool_name"],
            },
        },
    },
]


def build_tools(
    include_workspace_tools: bool = False,
    workspace_names: list[str] | None = None,
) -> tuple[list[dict], list[dict]]:
    """Build OpenAI and Anthropic tool lists.

    If *include_workspace_tools* is True, adds ``list_workspaces`` and
    ``query_other_workspace`` tools with the available workspace names
    injected into the descriptions.
    """
    openai_tools = list(CORPUS_TOOLS)
    if include_workspace_tools and workspace_names:
        ws_tools = []
        for tool in _WORKSPACE_TOOLS_OPENAI:
            ws_tools.append(tool)
        # Inject workspace names into query_other_workspace description
        names_str = ", ".join(f"'{n}'" for n in workspace_names)
        for tool in ws_tools:
            fn = tool["function"]
            if fn["name"] == "query_other_workspace":
                fn["description"] += f" Available workspaces: {names_str}."
        openai_tools.extend(ws_tools)

    anthropic_tools = _openai_to_anthropic(openai_tools)
    return openai_tools, anthropic_tools
