"""Añade N cards como fila horizontal al final de una tab de dashboard."""

from __future__ import annotations

from .client import MetabaseClient
from .metabase_dashboard_next_row import metabase_dashboard_next_row
from .metabase_copy_dashcard_mappings import metabase_copy_dashcard_mappings
from .metabase_update_dashboard_safe import metabase_update_dashboard_safe


def metabase_dashboard_append_row(
    client: MetabaseClient,
    *,
    dashboard_id: int,
    tab_id: int,
    card_ids: list[int],
    height: int = 4,
    donor_card_id: int = 0,
    grid_width: int = 24,
) -> dict:
    """Añade N cards como fila horizontal al final de una tab de dashboard.

    Calcula la primera fila libre de la tab indicada, distribuye las cards
    horizontalmente con ancho uniforme (``grid_width // len(card_ids)``) y
    opcionalmente copia los ``parameter_mappings`` de una card donante a cada
    nueva card. Internamente delega en ``metabase_dashboard_next_row``,
    ``metabase_copy_dashcard_mappings`` y ``metabase_update_dashboard_safe``.

    Args:
        client: MetabaseClient autenticado con sesion activa.
        dashboard_id: ID del dashboard donde se añaden las cards.
        tab_id: ID de la tab donde se insertan las cards. Usar ``0`` para
            dashboards sin tabs o para la tab raiz.
        card_ids: Lista de IDs de cards a colocar como fila. El orden de
            la lista determina el orden de izquierda a derecha.
        height: Altura en filas del grid para cada card. Default ``4``.
        donor_card_id: Si distinto de ``0``, copia los ``parameter_mappings``
            de esa card (que debe existir ya en el dashboard) a cada nueva
            card. Util para replicar los 18 filtros de dashboard sin configurar
            manualmente cada mapping. Default ``0`` (sin mappings).
        grid_width: Anchura total del grid de Metabase. Default ``24``
            (estandar de Metabase). Cada card recibe
            ``grid_width // len(card_ids)`` columnas.

    Returns:
        Dict con el resumen de la operacion devuelto por
        ``metabase_update_dashboard_safe``::

            {
                "added": [lista de IDs negativos asignados],
                "updated": int,   # dashcards existentes conservados
                "removed": int,   # dashcards eliminados (0 en este caso)
                "response": dict, # respuesta raw de PUT /api/dashboard/:id
            }

    Raises:
        ValueError: Si ``card_ids`` esta vacio, o si ``donor_card_id != 0``
            y esa card no existe en el dashboard.
        httpx.HTTPStatusError: Si la API de Metabase devuelve 4xx/5xx.

    Example:
        >>> # Añadir 4 KPIs al final de la tab 7, copiando filtros de card 42
        >>> result = metabase_dashboard_append_row(
        ...     client,
        ...     dashboard_id=10,
        ...     tab_id=7,
        ...     card_ids=[101, 102, 103, 104],
        ...     height=4,
        ...     donor_card_id=42,
        ... )
        >>> print(result["added"])  # [-1, -2, -3, -4]

        >>> # Sin filtros, 2 cards en dashboard sin tabs
        >>> result = metabase_dashboard_append_row(
        ...     client,
        ...     dashboard_id=10,
        ...     tab_id=0,
        ...     card_ids=[200, 201],
        ...     height=6,
        ... )
    """
    if not card_ids:
        raise ValueError("card_ids no puede estar vacio")

    # 1. Calcular siguiente fila libre
    next_row = metabase_dashboard_next_row(
        client, dashboard_id=dashboard_id, tab_id=tab_id
    )

    # 2. Ancho de cada card
    size_x = grid_width // len(card_ids)

    # 3. Construir dashcards
    new_dashcards: list[dict] = []
    for i, cid in enumerate(card_ids):
        # Copiar mappings del donor si se especifico
        if donor_card_id != 0:
            mappings = metabase_copy_dashcard_mappings(
                client,
                dashboard_id=dashboard_id,
                source_card_id=donor_card_id,
                dest_card_id=cid,
            )
        else:
            mappings = []

        dashcard: dict = {
            "card_id": cid,
            "dashboard_tab_id": tab_id,
            "row": next_row,
            "col": i * size_x,
            "size_x": size_x,
            "size_y": height,
            "parameter_mappings": mappings,
            "visualization_settings": {},
        }
        new_dashcards.append(dashcard)

    # 4. Actualizar el dashboard
    return metabase_update_dashboard_safe(
        client,
        dashboard_id,
        dashcards_add=new_dashcards,
    )
