import type { LucideIcon } from 'lucide-react'
import type { ReactNode } from 'react'

import {
  Card,
  CardAction,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from '@/components/ui/card'
import { cn } from '@/lib/utils'

interface Props {
  /** El nombre del indicador. Es el encabezado real de la tarjeta. */
  title: string
  /** Opcional, y a la izquierda del título. Nunca reemplaza a la palabra. */
  icon?: LucideIcon
  /**
   * Acompaña al título, en el encabezado.
   *
   * Para cuando el nombre del indicador no alcanza para decir qué mide. Es del
   * indicador y no de su valor de hoy: lo que explica la cifra es `description`.
   */
  subtitle?: string
  /**
   * La cifra, **ya formateada**.
   *
   * Llega como cadena y no como número a propósito: esta pieza no sabe si eso
   * es un conteo, un par de cifras («200 de 242»), un porcentaje o un guion, y
   * no tiene por qué saberlo. Separar miles y elegir el guion es de quien la usa.
   */
  value: string
  /** Qué significa la cifra, debajo de ella. Dos líneas como mucho. */
  description?: string
  /**
   * La ranura de la derecha del encabezado.
   *
   * **Esta tarjeta no sabe qué va acá y no pregunta.** Sólo reserva el lugar y
   * lo alinea; que sea un botón, un icono o un menú lo decide quien la usa.
   */
  actions?: ReactNode
  /** El pie. Ranura ciega también, y **no se rinde si viene vacía**. */
  footer?: ReactNode
  className?: string
  /** Debajo de la descripción, para lo que no entra en una oración. */
  children?: ReactNode
}

/**
 * Un indicador con nombre propio.
 *
 * Es la contracara de `MetricCard`, y la diferencia es el orden. En `MetricCard`
 * la cifra **es** el encabezado —por eso su etiqueta baja a `CardDescription`— y
 * el dato que la sostiene se va a la esquina superior derecha. Acá el encabezado
 * es el **nombre del indicador**, la cifra vive en el contenido como su
 * respuesta, y esa esquina queda libre para las acciones.
 */
export function IndicatorCard({
  title,
  icon: Icon,
  subtitle,
  value,
  description,
  actions,
  footer,
  className,
  children,
}: Props) {
  return (
    <Card className={cn('h-full gap-2', className)}>
      {/*
        El título va en `CardTitle` y el subtítulo en `CardDescription`, cada uno
        en su ranura. La acción se centra respecto del **bloque entero**: con
        subtítulo queda entre los dos renglones, y sin él, centrada con el
        título. La primitiva la ancla arriba —`self-start`— porque está pensada
        para `MetricCard`, que apila etiqueta y cifra.

        No envuelve: icono, título y acción son lo que fija el ancho mínimo de la
        tarjeta, y partirlos en dos renglones dejaría encabezados de distinto
        alto en una misma fila.
      */}
      <CardHeader className="whitespace-nowrap">
        {/*
          El grid del encabezado tiene **dos filas**. Con subtítulo, cada uno
          ocupa la suya. Sin subtítulo, el título abarca las dos —igual que la
          acción, que ya lo hace por la primitiva— y los dos quedan centrados
          sobre la misma región. Sin eso, el título se queda en la fila de
          arriba y la acción, que abarca ambas, se ve más abajo.
        */}
        <CardTitle asChild className={cn(!subtitle && 'row-span-2 self-center')}>
          <h3 className="text-muted-foreground flex min-w-0 items-center gap-2 text-sm">
            {Icon ? <Icon aria-hidden className="size-4 shrink-0" /> : null}
            <span className="truncate">{title}</span>
          </h3>
        </CardTitle>
        {subtitle ? <CardDescription className="truncate">{subtitle}</CardDescription> : null}
        {actions ? <CardAction className="self-center">{actions}</CardAction> : null}
      </CardHeader>

      {/*
        `flex-1` es lo que mantiene los pies alineados: sin él cada pie arranca
        donde termina su propia descripción, y una más larga que otra los deja a
        distinta altura en una fila de tarjetas de igual alto.
      */}
      <CardContent className="flex flex-1 flex-col gap-2">
        {/*
          La cifra es un párrafo y no otro `CardTitle`: el título de la tarjeta ya
          está arriba, y dos encabezados nombrando la misma caja compiten.

          30 px y no los 24 de T2: acá la cifra convive con un título arriba y una
          descripción abajo, y a 24 se leía como un dato más en vez de como la
          respuesta. Declarado en el contrato §3.4b.
        */}
        <p className="font-heading text-3xl font-semibold tabular-nums">{value}</p>
        {description ? (
          <p className="text-muted-foreground text-xs text-pretty">{description}</p>
        ) : null}
        {children}
      </CardContent>

      {/* Un pie vacío no se dibuja: le cambia el relleno a la tarjeta entera y
          deja una franja con borde y fondo sin nada escrito. */}
      {footer ? <CardFooter>{footer}</CardFooter> : null}
    </Card>
  )
}
