"""Schema exploration tools: list databases, tables, and field metadata."""

from __future__ import annotations

from typing import Any

from metaverse.app import mcp
from metaverse.client import as_dict, as_list
from metaverse.client import get as api_get


@mcp.tool()
async def list_databases() -> list[dict[str, Any]]:
    """List all databases connected to Metabase.

    Returns a list of {id, name, engine} dicts.
    Always call this first to obtain a database_id before listing tables or running queries.
    """
    data = await api_get("/database")
    return [
        {"id": db["id"], "name": db["name"], "engine": db.get("engine", "")} for db in as_list(data)
    ]


@mcp.tool()
async def list_tables(database_id: int) -> list[dict[str, Any]]:
    """List all tables in a database.

    Args:
        database_id: The database ID from list_databases.

    Returns a list of {id, name, schema, description} dicts.
    """
    data = as_dict(await api_get(f"/database/{database_id}/metadata"))
    return [
        {
            "id": t["id"],
            "name": t["name"],
            "schema": t.get("schema", "public"),
            "description": t.get("description") or "",
        }
        for t in data.get("tables", [])
    ]


@mcp.tool()
async def describe_table(table_id: int) -> dict[str, Any]:
    """Get the full schema for a table: column names, types, and relationships.

    Args:
        table_id: The table ID from list_tables.

    Returns {name, schema, fields: [{id, name, type, description, is_pk, fk_target}]}.
    The field id is required when calling create_metric.
    Call this before writing SQL — never guess column names.
    """
    data = as_dict(await api_get(f"/table/{table_id}/query_metadata"))
    fields: list[dict[str, Any]] = []
    for f in data.get("fields", []):
        fk_target = None
        if f.get("fk_target_field_id") and f.get("target"):
            target: dict[str, Any] = f["target"]
            fk_target = {
                "table": (target.get("table") or {}).get("name"),
                "field": target.get("name"),
            }
        fields.append(
            {
                "id": f["id"],
                "name": f["name"],
                "type": f.get("base_type", ""),
                "description": f.get("description") or "",
                "is_pk": f.get("semantic_type") == "type/PK",
                "fk_target": fk_target,
            }
        )
    return {
        "name": data["name"],
        "schema": data.get("schema", "public"),
        "fields": fields,
    }
