'use client';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { cn } from '@/lib/utils';
import { ArrowLeft, Search, type LucideIcon } from 'lucide-react';
import Link from 'next/link';
import type { ChangeEvent, ReactNode } from 'react';

/*
 * Encabezado de página.
 *
 * El diseño anterior tenía cinco temas de color (azul, esmeralda, ámbar, rosa,
 * pizarra), cada uno con degradado, halo radial y sombra propia. Eso hacía que
 * dos pantallas equivalentes se vieran como dos productos distintos, y que el
 * color no significara nada — el ámbar no quería decir "cuidado", sólo decía
 * "esta es la pantalla de catálogos".
 *
 * Ahora el encabezado es neutro en todas las pantallas. `tone` se conserva en
 * la firma porque lo pasan ~20 páginas, pero ya no pinta el fondo: sólo tiñe el
 * ícono, que alcanza para orientar sin convertir cada pantalla en un tema.
 */

const iconTones = {
  blue: 'bg-primary-soft text-primary',
  emerald: 'bg-success-soft text-success',
  amber: 'bg-warning-soft text-warning',
  rose: 'bg-destructive-soft text-destructive',
  slate: 'bg-muted text-muted-foreground',
} as const;

type Tone = keyof typeof iconTones;

type DashboardStat = {
  label: string;
  value: ReactNode;
  hint?: string;
  icon?: LucideIcon;
  href?: string;
};

type DashboardPageIntroProps = {
  title: string;
  description?: string;
  icon: LucideIcon;
  tone?: Tone;
  badge?: string;
  onBack?: () => void;
  actions?: ReactNode;
  stats?: DashboardStat[];
  /*
   * Controles de filtro de un listado (buscador, selects, chips). Es un slot
   * aparte de `children` para que quede siempre en el mismo lugar del header
   * en las ~20 páginas de listado, en vez de que cada una decida a mano si va
   * antes o después de las stats.
   */
  filters?: ReactNode;
  children?: ReactNode;
  className?: string;
};

export function DashboardPageIntro({
  title,
  description,
  icon: Icon,
  tone = 'blue',
  badge,
  onBack,
  actions,
  stats = [],
  filters,
  children,
  className,
}: DashboardPageIntroProps) {
  return (
    <section className={cn('mb-5 md:mb-6', className)}>
      <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
        <div className="flex min-w-0 items-start gap-3">
          {onBack ? (
            <Button
              variant="outline"
              size="icon"
              onClick={onBack}
              aria-label="Volver"
              className="shrink-0"
            >
              <ArrowLeft className="h-5 w-5" />
            </Button>
          ) : null}

          <span
            className={cn(
              'flex h-11 w-11 shrink-0 items-center justify-center rounded-xl',
              iconTones[tone] ?? iconTones.blue,
            )}
          >
            <Icon className="h-5 w-5" />
          </span>

          <div className="min-w-0 pt-0.5">
            <div className="flex flex-wrap items-center gap-2">
              <h2 className="text-2xl font-bold tracking-tight text-foreground">{title}</h2>
              {badge ? (
                <span className="rounded-full bg-muted px-2.5 py-0.5 text-xs font-medium text-muted-foreground">
                  {badge}
                </span>
              ) : null}
            </div>
            {description ? (
              <p className="mt-1.5 max-w-2xl text-base leading-relaxed text-muted-foreground sm:text-sm">
                {description}
              </p>
            ) : null}
          </div>
        </div>

        {/*
         * En celular los botones de acción ocupan todo el ancho y se apilan.
         * Antes se encogían para caber en una fila y quedaban de 30px de alto,
         * imposibles de acertar con el dedo.
         */}
        {actions ? (
          <div className="flex w-full shrink-0 flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center lg:w-auto [&>*]:w-full sm:[&>*]:w-auto">
            {actions}
          </div>
        ) : null}
      </div>

      {filters ? <div className="mt-4">{filters}</div> : null}

      {children ? <div className="mt-4">{children}</div> : null}

      {stats.length > 0 ? (
        <div className="mt-5 grid grid-cols-2 gap-3 lg:grid-cols-4">
          {stats.map((stat) => {
            const StatIcon = stat.icon;
            const content = (
              <div
                className={cn(
                  'h-full rounded-xl border border-border bg-card p-4 transition-colors duration-150',
                  stat.href && 'hover:border-border-strong hover:bg-muted/40',
                )}
              >
                {/* gap-3 y no gap-2: con etiquetas largas que parten en dos
                    líneas, el texto llegaba a rozar el ícono de la derecha. */}
                <div className="flex items-start justify-between gap-3">
                  <p className="min-w-0 text-sm font-medium text-muted-foreground">{stat.label}</p>
                  {StatIcon ? (
                    <StatIcon className="h-4 w-4 shrink-0 text-subtle-foreground" />
                  ) : null}
                </div>
                <div className="mt-2 break-words text-2xl font-bold tracking-tight text-foreground">
                  {stat.value}
                </div>
                {stat.hint ? (
                  <p className="mt-1 text-sm text-muted-foreground">{stat.hint}</p>
                ) : null}
              </div>
            );

            return stat.href ? (
              <Link
                key={stat.label}
                href={stat.href}
                className="block h-full rounded-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
              >
                {content}
              </Link>
            ) : (
              <div key={stat.label}>{content}</div>
            );
          })}
        </div>
      ) : null}
    </section>
  );
}

type DashboardSectionProps = {
  title: string;
  description?: string;
  action?: ReactNode;
  children: ReactNode;
  className?: string;
};

export function DashboardSection({
  title,
  description,
  action,
  children,
  className,
}: DashboardSectionProps) {
  return (
    <section
      className={cn(
        'overflow-hidden rounded-xl border border-border bg-card shadow-sm',
        className,
      )}
    >
      <div className="flex flex-col gap-3 border-b border-border px-4 py-4 md:flex-row md:items-center md:justify-between md:px-5">
        <div className="min-w-0">
          <h3 className="text-base font-semibold tracking-tight text-foreground">{title}</h3>
          {description ? (
            <p className="mt-1 max-w-2xl text-sm leading-relaxed text-muted-foreground">
              {description}
            </p>
          ) : null}
        </div>
        {action ? (
          <div className="flex w-full shrink-0 flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center md:w-auto [&>*]:w-full sm:[&>*]:w-auto">
            {action}
          </div>
        ) : null}
      </div>
      <div className="p-4 md:p-5">{children}</div>
    </section>
  );
}

type DashboardEmptyStateProps = {
  title: string;
  description: string;
  icon: LucideIcon;
  action?: ReactNode;
  className?: string;
};

export function DashboardEmptyState({
  title,
  description,
  icon: Icon,
  action,
  className,
}: DashboardEmptyStateProps) {
  return (
    <div className={cn('px-6 py-12 text-center', className)}>
      <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-muted text-muted-foreground">
        <Icon className="h-6 w-6" />
      </div>
      <h3 className="mt-4 text-base font-semibold tracking-tight text-foreground">{title}</h3>
      <p className="mx-auto mt-2 max-w-md text-base leading-relaxed text-muted-foreground sm:text-sm">
        {description}
      </p>
      {action ? <div className="mt-5 flex justify-center">{action}</div> : null}
    </div>
  );
}

type DashboardToolbarProps = {
  /** Valor controlado del buscador. Omitilo si el listado no tiene búsqueda. */
  searchValue?: string;
  onSearchChange?: (value: string) => void;
  searchPlaceholder?: string;
  /**
   * Controles adicionales (selects de estado, chips de filtro, etc). Cada
   * listado reimplementaba a mano "buscador + filtros + botón" con su propio
   * layout de flex — acá queda en un solo lugar para que los ~20 listados no
   * diverjan en espaciado ni en el orden búsqueda/filtros/acción.
   */
  filters?: ReactNode;
  /** Acción primaria del listado (ej. "Nuevo registro"). Va siempre al final. */
  action?: ReactNode;
  className?: string;
};

export function DashboardToolbar({
  searchValue,
  onSearchChange,
  searchPlaceholder = 'Buscar',
  filters,
  action,
  className,
}: DashboardToolbarProps) {
  const hasSearch = onSearchChange !== undefined;

  const handleSearchChange = (event: ChangeEvent<HTMLInputElement>) => {
    onSearchChange?.(event.target.value);
  };

  return (
    <div
      className={cn(
        'flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center',
        className,
      )}
    >
      {hasSearch ? (
        <div className="relative w-full sm:max-w-xs">
          <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-subtle-foreground" />
          <Input
            value={searchValue ?? ''}
            onChange={handleSearchChange}
            placeholder={searchPlaceholder}
            aria-label={searchPlaceholder}
            className="h-11 pl-9"
          />
        </div>
      ) : null}

      {filters ? (
        <div className="flex w-full flex-wrap items-center gap-2 sm:w-auto">{filters}</div>
      ) : null}

      {/* mt-auto en desktop no hace falta: sm:ml-auto empuja la acción a la
          derecha sin que la fila entera crezca por ella. */}
      {action ? <div className="w-full sm:ml-auto sm:w-auto">{action}</div> : null}
    </div>
  );
}

type DashboardListRowProps = {
  /** Ícono o avatar a la izquierda. Ya viene con el contenedor circular. */
  icon?: ReactNode;
  title: ReactNode;
  /** Línea secundaria: placa, teléfono, fecha, lo que identifique el registro. */
  meta?: ReactNode;
  /** Botones/menú de acciones, alineados a la derecha. */
  actions?: ReactNode;
  href?: string;
  onClick?: () => void;
  className?: string;
};

/*
 * Fila de listado "mobile-friendly": 64px de alto mínimo para que el dedo la
 * acierte, con ícono + título + metadato + acciones. Es la variante que
 * reemplaza una fila de <table> cuando las columnas no caben en una pantalla
 * angosta — no un reemplazo de Table en desktop, donde las columnas sí caben.
 */
export function DashboardListRow({
  icon,
  title,
  meta,
  actions,
  href,
  onClick,
  className,
}: DashboardListRowProps) {
  const isInteractive = Boolean(href || onClick);

  const content = (
    <div
      className={cn(
        'flex min-h-[64px] w-full items-center gap-3 border-b border-border px-4 py-3 last:border-b-0',
        isInteractive &&
          'text-left transition-[background-color,transform] duration-150 ease-out [@media(hover:hover)]:hover:bg-muted/40 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset',
        className,
      )}
    >
      {icon ? (
        <span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground">
          {icon}
        </span>
      ) : null}

      <div className="min-w-0 flex-1">
        <p className="truncate text-sm font-semibold text-foreground">{title}</p>
        {meta ? <p className="mt-0.5 truncate text-sm text-muted-foreground">{meta}</p> : null}
      </div>

      {actions ? (
        <div className="flex shrink-0 items-center gap-1" onClick={(event) => event.stopPropagation()}>
          {actions}
        </div>
      ) : null}
    </div>
  );

  if (href) {
    return (
      <Link href={href} className="block">
        {content}
      </Link>
    );
  }

  if (onClick) {
    return (
      <button type="button" onClick={onClick} className="block w-full">
        {content}
      </button>
    );
  }

  return content;
}
