"""CRUD de SQL snippets de Metabase.

Un snippet es un fragmento SQL reutilizable que se referencia en queries
nativas con la sintaxis {{snippet: nombre}}. Ideal para CTEs comunes
que se repiten en multiples cards.
"""

from .client import MetabaseClient


def metabase_list_snippets(client: MetabaseClient, archived: bool = False) -> list[dict]:
    """Lista SQL snippets de Metabase.

    Endpoint: GET /api/native-query-snippet.

    Args:
        client: Cliente autenticado.
        archived: Si True, incluye snippets archivados.

    Returns:
        Lista de dicts con: id, name, content, description, collection_id,
        creator_id, archived, created_at, updated_at.

    Example:
        >>> snippets = metabase_list_snippets(client)
        >>> for s in snippets:
        ...     print(s["name"], len(s["content"]))
    """
    params = {}
    if archived:
        params["archived"] = "true"
    return client.request("GET", "/api/native-query-snippet", params=params)


def metabase_get_snippet(client: MetabaseClient, snippet_id: int) -> dict:
    """Obtiene un SQL snippet de Metabase por su ID.

    Endpoint: GET /api/native-query-snippet/:id.

    Args:
        client: Cliente autenticado.
        snippet_id: ID numerico del snippet.

    Returns:
        Dict con campos completos del snippet: id, name, content, description,
        collection_id, creator_id, archived, created_at, updated_at.

    Raises:
        httpx.HTTPStatusError: 404 si el snippet no existe.

    Example:
        >>> snippet = metabase_get_snippet(client, 42)
        >>> print(snippet["name"], snippet["content"])
    """
    return client.request("GET", f"/api/native-query-snippet/{snippet_id}")


def metabase_create_snippet(
    client: MetabaseClient,
    name: str,
    content: str,
    description: str = "",
    collection_id: int = 0,
) -> dict:
    """Crea un nuevo SQL snippet en Metabase.

    Endpoint: POST /api/native-query-snippet.

    Args:
        client: Cliente autenticado.
        name: Nombre del snippet. Se usa en queries con {{snippet: nombre}}.
        content: SQL del snippet. Puede ser una CTE completa, una subquery,
            o cualquier fragmento SQL reutilizable.
        description: Descripcion opcional del snippet.
        collection_id: ID de la coleccion donde guardar el snippet.
            Si es 0, se guarda en la raiz (Our analytics).

    Returns:
        Dict con el snippet creado, incluyendo el campo "id" asignado
        por Metabase.

    Raises:
        httpx.HTTPStatusError: 400 si el nombre ya existe o el SQL es invalido.

    Example:
        >>> snippet = metabase_create_snippet(
        ...     client,
        ...     "supply_orders_cte",
        ...     '''WITH supply_full AS (
        ...         SELECT so.id, so.service_request_id
        ...         FROM supply_orders so
        ...         LEFT JOIN service_requests sr ON so.service_request_id = sr.id
        ...     )''',
        ...     description="CTE base de supply_orders con JOINs para cruce con NAV",
        ... )
        >>> print(snippet["id"], snippet["name"])
        >>> # Usar en una card:
        >>> # "{{snippet: supply_orders_cte}} SELECT ... FROM supply_full"
    """
    body: dict = {"name": name, "content": content}
    if description:
        body["description"] = description
    if collection_id:
        body["collection_id"] = collection_id
    return client.request("POST", "/api/native-query-snippet", json=body)


def metabase_update_snippet(
    client: MetabaseClient,
    snippet_id: int,
    **fields,
) -> dict:
    """Actualiza campos de un SQL snippet en Metabase.

    Endpoint: PUT /api/native-query-snippet/:id.

    Args:
        client: Cliente autenticado.
        snippet_id: ID numerico del snippet a actualizar.
        **fields: Campos a modificar. Campos validos:
            - name (str): Nuevo nombre del snippet.
            - content (str): Nuevo SQL del snippet.
            - description (str): Nueva descripcion.
            - collection_id (int): Nueva coleccion.
            - archived (bool): True para archivar, False para desarchivar.

    Returns:
        Dict con el snippet actualizado.

    Raises:
        httpx.HTTPStatusError: 404 si el snippet no existe.
        httpx.HTTPStatusError: 400 si los campos son invalidos.

    Example:
        >>> updated = metabase_update_snippet(
        ...     client, 42,
        ...     content="WITH supply_full AS (SELECT * FROM supply_orders)",
        ...     description="Version simplificada",
        ... )
        >>> print(updated["updated_at"])
    """
    valid_fields = {"name", "content", "description", "collection_id", "archived"}
    body = {k: v for k, v in fields.items() if k in valid_fields}
    return client.request("PUT", f"/api/native-query-snippet/{snippet_id}", json=body)


def metabase_archive_snippet(client: MetabaseClient, snippet_id: int) -> dict:
    """Archiva un SQL snippet en Metabase.

    Wrapper sobre metabase_update_snippet con archived=True.
    Los snippets archivados no aparecen en el autocomplete de queries
    pero sus referencias existentes siguen funcionando.

    Endpoint: PUT /api/native-query-snippet/:id.

    Args:
        client: Cliente autenticado.
        snippet_id: ID numerico del snippet a archivar.

    Returns:
        Dict con el snippet archivado.

    Raises:
        httpx.HTTPStatusError: 404 si el snippet no existe.

    Example:
        >>> result = metabase_archive_snippet(client, 42)
        >>> print(result["archived"])  # True
    """
    return metabase_update_snippet(client, snippet_id, archived=True)
