import type { LucideIcon } from 'lucide-react'

import { Badge } from '@/components/ui/badge'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { cn } from '@/lib/utils'

/**
 * Los cinco tonos son un juego **cerrado**. No se agrega un sexto: el día que
 * haga falta uno, lo que hay que revisar es qué significa el estado, no la
 * paleta.
 */
export type StatusTone = 'positive' | 'attention' | 'critical' | 'neutral' | 'unknown'

/**
 * `unknown` no es un tono negativo y por eso no comparte familia con ninguno.
 *
 * Borde punteado, sin relleno y muted es la forma de decir «todavía no
 * preguntamos» (RT-03). Teñirlo de ámbar lo agruparía con lo que sí está mal, y
 * eso sería afirmar algo que nadie comprobó.
 */
const TONES: Record<
  StatusTone,
  { variant: 'secondary' | 'destructive' | 'outline'; className?: string }
> = {
  positive: {
    variant: 'outline',
    className: 'border-emerald-600/30 bg-emerald-600/10 text-emerald-800 dark:text-emerald-300',
  },
  attention: {
    variant: 'outline',
    className: 'border-amber-600/40 bg-amber-600/10 text-amber-800 dark:text-amber-300',
  },
  critical: { variant: 'destructive' },
  neutral: { variant: 'outline' },
  unknown: {
    variant: 'outline',
    className: 'border-dashed border-muted-foreground/40 bg-transparent text-muted-foreground',
  },
}

interface Props {
  tone: StatusTone
  /**
   * El dibujo del estado, que es **independiente del tono**.
   *
   * Un estado real que hoy no podemos confirmar se rinde con `tone="unknown"`
   * conservando su propio icono y su propia palabra: bajar el tono dice que no
   * lo pudimos verificar, y reescribir la etiqueta diría que el estado es otro.
   */
  icon: LucideIcon
  /** Una palabra o una frase corta. Nunca una oración: rompe la fila de la tabla. */
  children: string
  /** La explicación en un `Tooltip`. La palabra se lee igual sin abrirlo. */
  help?: string
  className?: string
}

/**
 * La única forma de badge de estado del producto.
 *
 * Antes convivían dos: un `<span>` dibujado a mano con `rounded-md border` y el
 * `ui/badge` con `rounded-4xl`. El mismo concepto con dos radios distintos hace
 * que dos pantallas parezcan de dos productos, y obliga a decidir de nuevo la
 * forma cada vez que aparece un estado nuevo.
 *
 * Dos reglas viajan con la pieza:
 *
 * - **Icono primero, palabra después** (RT-04). Nunca sólo icono, nunca sólo
 *   color: la prueba es la captura en escala de grises, donde los estados se
 *   tienen que seguir distinguiendo.
 * - El `help` va en un `Tooltip` y no en un `title=`, porque `title` no se
 *   alcanza con el teclado ni existe en táctil (RT-02). Por eso el badge con
 *   ayuda es enfocable: si no se puede tabular hasta él, el arreglo no arregla
 *   nada.
 */
export function StatusBadge({ tone, icon: Icon, children, help, className }: Props) {
  const style = TONES[tone]

  const badge = (
    <Badge
      variant={style.variant}
      // El tono viaja al marcado para que se pueda comprobar desde afuera qué
      // familia le tocó a cada estado sin tener que leer la lista de clases.
      data-tone={tone}
      // `help` **no** va acá: es una frase traducida, no una lista de clases.
      // Pasarla a `cn()` metía la explicación entera —palabra por palabra— en
      // el atributo `class` del badge. Hoy ninguna de esas palabras coincide
      // con una utilidad de Tailwind, así que no se veía; alcanzaba con que una
      // traducción futura dijera «block» o «hidden» para romper el badge sin
      // que nada lo relacionara con el catálogo.
      className={cn(style.className, className)}
      tabIndex={help ? 0 : undefined}
    >
      <Icon aria-hidden className="size-3" />
      {children}
    </Badge>
  )

  if (!help) return badge

  return (
    <Tooltip>
      <TooltipTrigger asChild>{badge}</TooltipTrigger>
      <TooltipContent>{help}</TooltipContent>
    </Tooltip>
  )
}
