"""Gestion de routines (UDFs y stored procedures) en Google BigQuery."""

from .client import BQClient
from google.cloud import bigquery


def bq_create_routine(
    client: BQClient,
    dataset_id: str,
    routine_id: str,
    body: str,
    routine_type: str = "SCALAR_FUNCTION",
    language: str = "SQL",
    arguments: list[dict] | None = None,
    return_type: str = "",
    description: str = "",
) -> dict:
    """Crea una routine (UDF o stored procedure) en BigQuery.

    Args:
        client: Cliente autenticado.
        dataset_id: ID del dataset donde crear la routine.
        routine_id: ID/nombre de la routine.
        body: Cuerpo de la routine (SQL, JavaScript o Python).
        routine_type: Tipo: "SCALAR_FUNCTION", "TABLE_VALUED_FUNCTION", "PROCEDURE".
        language: Lenguaje: "SQL", "JAVASCRIPT", "PYTHON".
        arguments: Lista de argumentos, cada uno: {"name": "x", "data_type": "STRING"}.
        return_type: Tipo de retorno para funciones (ej: "STRING", "INT64"). No aplica a procedures.
        description: Descripcion opcional.

    Returns:
        Dict con: routine_id, dataset_id, project, routine_type, language, body, created, modified.

    Raises:
        google.api_core.exceptions.Conflict: Si la routine ya existe.

    Example:
        >>> bq_create_routine(client, "analytics", "double_value",
        ...     body="x * 2",
        ...     arguments=[{"name": "x", "data_type": "INT64"}],
        ...     return_type="INT64")
    """
    ref = bigquery.RoutineReference.from_string(
        f"{client.project_id}.{dataset_id}.{routine_id}"
    )
    routine = bigquery.Routine(ref)
    routine.type_ = routine_type
    routine.language = language
    routine.body = body
    if description:
        routine.description = description
    if arguments:
        routine.arguments = [
            bigquery.RoutineArgument(
                name=arg["name"],
                data_type=bigquery.StandardSqlDataType(
                    type_kind=getattr(
                        bigquery.StandardSqlTypeNames, arg["data_type"]
                    )
                ),
            )
            for arg in arguments
        ]
    if return_type:
        routine.return_type = bigquery.StandardSqlDataType(
            type_kind=getattr(bigquery.StandardSqlTypeNames, return_type)
        )
    created = client._client.create_routine(routine)
    return _routine_to_dict(created)


def bq_list_routines(client: BQClient, dataset_id: str) -> list[dict]:
    """Lista routines de un dataset.

    Args:
        client: Cliente autenticado.
        dataset_id: ID del dataset.

    Returns:
        Lista de dicts con: routine_id, dataset_id, project, routine_type, language.

    Example:
        >>> routines = bq_list_routines(client, "analytics")
        >>> for r in routines:
        ...     print(r["routine_id"], r["routine_type"], r["language"])
    """
    ref = f"{client.project_id}.{dataset_id}"
    return [
        {
            "routine_id": r.routine_id,
            "dataset_id": dataset_id,
            "project": client.project_id,
            "routine_type": r.type_,
            "language": r.language,
        }
        for r in client._client.list_routines(ref)
    ]


def bq_delete_routine(
    client: BQClient,
    dataset_id: str,
    routine_id: str,
) -> None:
    """Elimina una routine.

    Args:
        client: Cliente autenticado.
        dataset_id: ID del dataset.
        routine_id: ID de la routine a eliminar.

    Raises:
        google.api_core.exceptions.NotFound: Si la routine no existe.

    Example:
        >>> bq_delete_routine(client, "analytics", "double_value")
    """
    ref = f"{client.project_id}.{dataset_id}.{routine_id}"
    client._client.delete_routine(ref)


def _routine_to_dict(routine) -> dict:
    """Convierte un objeto Routine del SDK a dict plano."""
    return {
        "routine_id": routine.routine_id,
        "dataset_id": routine.dataset_id,
        "project": routine.project,
        "routine_type": routine.type_,
        "language": routine.language,
        "body": routine.body,
        "description": routine.description or "",
        "created": routine.created.isoformat() if routine.created else None,
        "modified": routine.modified.isoformat() if routine.modified else None,
    }
