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

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

interface Props {
  /** Hasta cuatro palabras. Es el encabezado real de la tarjeta. */
  label: string
  /** Una cifra o un par de cifras («92 de 120»). **Jamás una palabra de estado.** */
  value: ReactNode
  /**
   * El dato que sostiene la cifra: el total, lo que falta, el resto.
   *
   * Tiene que hablar de **esta** cifra. Un estado que pertenece a otra cosa
   * —el del último ciclo al lado del conteo de lotes de hoy— se lee como si la
   * calificara: «0» con un «Parcial» al lado dice que ese cero quedó a medias.
   * Eso va en la nota, junto a la oración que lo nombra.
   */
  denominator?: ReactNode
  /**
   * Hasta dos líneas.
   *
   * Acepta marcado porque una nota puede llevar el badge del estado del que
   * habla; el estilo de prosa lo pone la tarjeta.
   */
  note?: ReactNode
  /**
   * Cuándo se obtuvo el dato. `null` se dibuja como «sin fecha»; omitirlo saca
   * el pie entero, para las cifras que no vienen de una consulta a Google.
   */
  fetchedAt?: string | null
  action?: ReactNode
  tone?: 'default' | 'unknown'
}

/**
 * Una cifra con lo que la mantiene honesta.
 *
 * El encabezado de la tarjeta es la **etiqueta**, no el número: T2 nunca es una
 * etiqueta de encabezado, porque una cifra no nombra nada —es el valor de algo
 * que ya tiene nombre—. Por eso el `h3` va en `CardDescription` y el título se
 * queda como `<div>` con el número adentro. Es la excepción declarada al arreglo
 * de `CardTitle`, y la única del contrato.
 *
 * `tone="unknown"` no es otra tarjeta: es esta misma en la familia visual de
 * RT-03. «Sin consultar todavía» dibujado aparte es lo que hace que un dato que
 * no tenemos se lea como un dato malo.
 *
 * Ninguna flecha de tendencia, nunca. Una variación porcentual sobre una muestra
 * parcial del sitio sugiere una serie histórica comparable donde sólo hay lo que
 * se alcanzó a consultar.
 */
export function MetricCard({
  label,
  value,
  denominator,
  note,
  fetchedAt,
  action,
  tone = 'default',
}: Props) {
  const unknown = tone === 'unknown'
  const hasFooter = fetchedAt !== undefined || action !== undefined

  return (
    <Card
      size="sm"
      className={cn(
        'h-full',
        // El anillo de la primitiva no puede ser punteado, así que la familia
        // de RT-03 se dibuja con un `outline`: sin relleno, punteado y muted es
        // la forma de decir «todavía no preguntamos» sin teñirlo de problema.
        unknown &&
          'bg-transparent text-muted-foreground ring-0 outline-1 outline-dashed outline-muted-foreground/40'
      )}
    >
      <CardHeader>
        <CardDescription asChild>
          <h3 className="flex items-center gap-1.5">
            {unknown ? <Clock aria-hidden className="size-3.5 shrink-0" /> : null}
            {label}
          </h3>
        </CardDescription>
        {/* El `!` es lo único que hace que la cifra mida 24 px: en una tarjeta
            `size="sm"` la propia primitiva baja el título a 14 px, y esa regla
            gana por orden de generación. Sin él, T2 se rinde como T4. */}
        <CardTitle className="text-2xl! font-semibold tabular-nums">{value}</CardTitle>
        {denominator !== undefined ? (
          <CardAction className="text-muted-foreground text-xs tabular-nums">
            {denominator}
          </CardAction>
        ) : null}
      </CardHeader>

      {note ? (
        <CardContent className="text-muted-foreground text-pretty">{note}</CardContent>
      ) : null}

      {hasFooter ? (
        // `mt-auto` empuja el pie contra el piso de la tarjeta. Sin él, en una
        // fila de tarjetas de igual alto las acciones quedan a distinta altura
        // —hasta 71 px de diferencia medidos en el tablero— porque cada una
        // arranca donde termina su propia nota, que es más corta o más larga
        // según el aspecto. El contrato lo pide en la regla 11.
        <CardFooter className="mt-auto justify-between gap-2">
          <span className="text-muted-foreground min-w-0 text-xs">
            {fetchedAt !== undefined ? <DataTimestamp value={fetchedAt} /> : null}
          </span>
          {action}
        </CardFooter>
      ) : null}
    </Card>
  )
}
