import { useEffect, useRef, useState } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { type Pedido, type PedidoItem } from '@gustito/shared';
import { Icono } from '@gustito/shared/iconos';
import { supabase } from '../lib/supabase';
import { useCambiosRestaurante } from '../lib/tiemporeal';
import { useTraidaAgrupada } from '../lib/agrupador';
import { parsearOpciones } from '../lib/opciones';
import DisponibilidadRapida from './DisponibilidadRapida';
import IndicadorConexion from '../components/IndicadorConexion';

type PedidoCocina = Pedido & { pedido_items: PedidoItem[] };

// Estados que le importan a la cocina: aprobado por el encargado (confirmado) y en preparacion.
const ESTADOS_COCINA = ['confirmado', 'preparando'] as const;

function beep() {
  try {
    const ctx = new AudioContext();
    const o = ctx.createOscillator();
    const g = ctx.createGain();
    o.frequency.value = 880;
    o.connect(g);
    g.connect(ctx.destination);
    o.start();
    setTimeout(() => o.stop(), 160);
    setTimeout(() => {
      o.disconnect();
      ctx.close();
    }, 220);
  } catch {
    /* sin audio disponible */
  }
}

function tipoTexto(p: PedidoCocina): string {
  if (p.tipo_entrega === 'delivery') return 'Delivery';
  if (p.tipo_entrega === 'mesa') return `Mesa ${p.mesa ?? ''}`.trim();
  return 'Para retirar';
}

function mmss(ms: number): string {
  const s = Math.max(0, Math.floor(ms / 1000));
  const m = Math.floor(s / 60);
  return `${m}:${String(s % 60).padStart(2, '0')}`;
}

// Color del cronometro segun cuanto lleva esperando.
function colorTiempo(min: number): string {
  if (min >= 15) return '#EF4444'; // rojo: urgente
  if (min >= 8) return '#F59E0B'; // ambar: apurando
  return '#22C55E'; // verde: a tiempo
}

export default function Cocina({ restauranteId }: { restauranteId: string }) {
  const qc = useQueryClient();
  const [ahora, setAhora] = useState(() => Date.now());
  const [full, setFull] = useState(false);
  const [agotar, setAgotar] = useState(false);
  const boardRef = useRef<HTMLDivElement>(null);

  const { data, isLoading, error } = useQuery({
    queryKey: ['cocina', restauranteId],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('pedidos')
        .select('*, pedido_items(*)')
        .eq('restaurante_id', restauranteId)
        .in('estado', ESTADOS_COCINA as unknown as string[])
        .order('recibido_en', { ascending: true });
      if (error) throw error;
      return (data ?? []) as unknown as PedidoCocina[];
    },
    refetchInterval: 12000,
  });

  // Reloj vivo (cronometros + hora).
  useEffect(() => {
    const t = setInterval(() => setAhora(Date.now()), 1000);
    return () => clearInterval(t);
  }, []);

  // Pantalla completa (tablet).
  useEffect(() => {
    const onFs = () => setFull(!!document.fullscreenElement);
    document.addEventListener('fullscreenchange', onFs);
    return () => document.removeEventListener('fullscreenchange', onFs);
  }, []);

  async function toggleFull() {
    try {
      if (document.fullscreenElement) await document.exitFullscreen();
      else await boardRef.current?.requestFullscreen();
    } catch {
      /* algunos navegadores lo bloquean */
    }
  }

  // Tiempo real: cuando un pedido cambia, traemos SOLO ese pedido (con sus items) y lo
  // empalmamos en la cola, en vez de rebajar toda la cocina en cada evento. El ticket
  // aparece igual de instantaneo y suena igual, pero movemos un pedido y no todo el
  // historial (clave cuando hay muchos locales a la vez). El poll de 12s se queda de red,
  // y ademas es lo que resincroniza esta pantalla si pasa horas prendida y el canal
  // se cae sin que nadie lo note (ver IndicadorConexion en el header).
  // Los pedidos que cambian se traen JUNTOS: una tanda de comandas confirmadas
  // disparaba una consulta por cada una y con eso el navegador de la cocina se
  // quedaba sin recursos justo en hora pico. Ver lib/agrupador.ts.
  const traerPedidos = useTraidaAgrupada<PedidoCocina>(
    async (ids) => {
      const { data } = await supabase.from('pedidos').select('*, pedido_items(*)').in('id', ids);
      return (data as unknown as PedidoCocina[]) ?? [];
    },
    (filas) => {
      if (filas.length === 0) return;
      qc.setQueryData<PedidoCocina[]>(['cocina', restauranteId], (prev) => {
        if (!prev) return prev;
        const nuevos = new Map(filas.map((f) => [f.id, f]));
        const otros = prev.filter((p) => !nuevos.has(p.id));
        return [...otros, ...nuevos.values()].sort(
          (a, b) => new Date(a.recibido_en).getTime() - new Date(b.recibido_en).getTime(),
        );
      });
    },
  );

  useCambiosRestaurante(restauranteId, {
    onCambio: async (c) => {
      if (c.tabla !== 'pedidos') return;
      if (c.nuevo?.estado === 'confirmado' && c.viejo?.estado !== 'confirmado') beep();

      const enCocina = c.nuevo?.estado != null && (ESTADOS_COCINA as readonly string[]).includes(c.nuevo.estado);

      // Salio de cocina (listo/entregado/cancelado) o lo borraron: quitarlo de la cola.
      if (c.accion === 'DELETE' || !enCocina) {
        qc.setQueryData<PedidoCocina[]>(['cocina', restauranteId], (prev) =>
          prev ? prev.filter((p) => p.id !== c.id) : prev,
        );
        return;
      }

      // Entro o cambio dentro de cocina: traer los pedidos que cambiaron y
      // empalmarlos. Si llegan varios avisos de golpe (una tanda de comandas
      // confirmadas), salen todos en UNA consulta y no una por cada uno.
      traerPedidos(c.id);
    },
    // La pantalla desperto o el canal volvio tras una caida: la cola pudo quedar
    // desactualizada (fila-por-fila no reconstruye lo perdido), refrescarla entera.
    onResync: () => qc.invalidateQueries({ queryKey: ['cocina', restauranteId] }),
  });

  async function avanzar(id: string, nuevo: 'preparando' | 'listo') {
    const { error } = await supabase.rpc('cambiar_estado_pedido', {
      p_pedido_id: id,
      p_nuevo_estado: nuevo,
    });
    if (error) alert(error.message);
    else qc.invalidateQueries({ queryKey: ['cocina', restauranteId] });
  }

  const pedidos = data ?? [];
  // Solo lo que se cocina: oculta las bebidas y los pedidos de solo bebidas.
  const conCocina = pedidos.filter((p) => (p.pedido_items ?? []).some((it) => it.a_cocina !== false));
  const nuevos = conCocina.filter((p) => p.estado === 'confirmado');
  const enPrep = conCocina.filter((p) => p.estado === 'preparando');
  const esperaMax = conCocina.length
    ? Math.max(...conCocina.map((p) => Math.floor((ahora - new Date(p.recibido_en).getTime()) / 60000)))
    : 0;

  const reloj = new Date(ahora);
  const horaTxt = `${String(reloj.getHours()).padStart(2, '0')}:${String(reloj.getMinutes()).padStart(2, '0')}`;

  return (
    <div
      ref={boardRef}
      className={`rounded-2xl bg-zinc-950 text-white ${full ? 'h-screen overflow-auto p-5' : 'p-4'}`}
    >
      {/* Barra de control */}
      <header className="flex flex-wrap items-center justify-between gap-3 border-b border-white/10 pb-3">
        <div className="flex items-center gap-2">
          <Icono nombre="cocina" className="h-6 w-6 text-white" />
          <h2 className="text-xl font-black tracking-tight">COCINA</h2>
          <span className="ml-1 font-mono text-lg font-bold text-white/70">{horaTxt}</span>
        </div>
        <div className="flex items-center gap-2">
          <IndicadorConexion restauranteId={restauranteId} />
          <Stat label="Por preparar" valor={nuevos.length} color="#38BDF8" />
          <Stat label="En preparación" valor={enPrep.length} color="#F59E0B" />
          <Stat label="Espera máx" valor={`${esperaMax}m`} color={colorTiempo(esperaMax)} />
          <button
            onClick={() => setAgotar(true)}
            className="rounded-lg bg-white/10 px-3 py-2 text-sm font-bold text-white ring-1 ring-white/15 hover:bg-white/20"
          >
            Agotados
          </button>
          <button
            onClick={toggleFull}
            className="rounded-lg bg-white/10 px-3 py-2 text-sm font-bold text-white ring-1 ring-white/15 hover:bg-white/20"
          >
            {full ? 'Salir' : 'Pantalla completa'}
          </button>
        </div>
      </header>

      {agotar && <DisponibilidadRapida restauranteId={restauranteId} onCerrar={() => setAgotar(false)} />}

      {isLoading && <p className="py-16 text-center text-white/60">Cargando cocina...</p>}
      {error && <p className="py-16 text-center text-red-400">{(error as Error).message}</p>}

      {!isLoading && !error && pedidos.length === 0 && (
        <div className="py-20 text-center">
          <Icono nombre="cocina" className="mx-auto h-14 w-14 text-white/30" />
          <p className="mt-3 text-lg font-bold text-white/90">Todo al día.</p>
          <p className="text-sm text-white/60">Cuando el encargado apruebe un pedido, aparece aquí y suena.</p>
        </div>
      )}

      {nuevos.length > 0 && (
        <Seccion titulo="Por preparar" punto="#38BDF8">
          {nuevos.map((p) => (
            <Ticket key={p.id} p={p} ahora={ahora} onAvanzar={() => avanzar(p.id, 'preparando')} />
          ))}
        </Seccion>
      )}

      {enPrep.length > 0 && (
        <Seccion titulo="En preparacion" punto="#F59E0B">
          {enPrep.map((p) => (
            <Ticket key={p.id} p={p} ahora={ahora} enPrep onAvanzar={() => avanzar(p.id, 'listo')} />
          ))}
        </Seccion>
      )}
    </div>
  );
}

function Stat({ label, valor, color }: { label: string; valor: number | string; color: string }) {
  return (
    <div className="rounded-lg bg-white/5 px-3 py-1.5 text-center ring-1 ring-white/10">
      <p className="text-lg font-black leading-none" style={{ color }}>
        {valor}
      </p>
      <p className="mt-0.5 text-[10px] font-bold uppercase tracking-wide text-white/65">{label}</p>
    </div>
  );
}

function Seccion({ titulo, punto, children }: { titulo: string; punto: string; children: React.ReactNode }) {
  return (
    <section className="mt-4">
      <div className="mb-2 flex items-center gap-2">
        <span className="h-2.5 w-2.5 rounded-full" style={{ backgroundColor: punto }} />
        <h3 className="text-sm font-extrabold uppercase tracking-wide text-white/90">{titulo}</h3>
      </div>
      <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">{children}</div>
    </section>
  );
}

function Ticket({
  p,
  ahora,
  enPrep = false,
  onAvanzar,
}: {
  p: PedidoCocina;
  ahora: number;
  enPrep?: boolean;
  onAvanzar: () => void;
}) {
  const ms = ahora - new Date(p.recibido_en).getTime();
  const min = Math.floor(ms / 60000);
  const color = colorTiempo(min);
  return (
    <article className="flex flex-col overflow-hidden rounded-2xl bg-zinc-900 ring-1 ring-white/15">
      {/* Cabecera del ticket: numero de orden + cronometro */}
      <div className="flex items-center justify-between px-3 py-2" style={{ backgroundColor: color }}>
        <span className="text-lg font-black text-black/90">#{p.codigo}</span>
        <span className="font-mono text-lg font-black text-black/90">{mmss(ms)}</span>
      </div>

      <div className="flex flex-1 flex-col p-3">
        <div className="mb-2 flex flex-wrap items-center gap-1.5">
          <span className="rounded-md bg-white/10 px-2 py-0.5 text-xs font-bold text-white/90">{tipoTexto(p)}</span>
          {p.para_llevar && (
            <span className="rounded-md bg-amber-400/20 px-2 py-0.5 text-xs font-black text-amber-300 ring-1 ring-amber-400/40">
              PARA LLEVAR
            </span>
          )}
          {p.mesero_nombre && (
            <span className="rounded-md bg-white/10 px-2 py-0.5 text-xs font-bold text-white/75">
              Atiende {p.mesero_nombre}
            </span>
          )}
          <span
            className="rounded-md px-2 py-0.5 text-xs font-bold"
            style={{
              backgroundColor: enPrep ? 'rgba(245,158,11,0.18)' : 'rgba(56,189,248,0.18)',
              color: enPrep ? '#FCD34D' : '#7DD3FC',
            }}
          >
            {enPrep ? 'En preparación' : 'Nuevo'}
          </span>
        </div>

        <ul className="flex-1 space-y-2.5">
          {p.pedido_items?.filter((it) => it.a_cocina !== false).map((it) => {
            const { grupos, libre } = parsearOpciones(it.nota);
            return (
              <li key={it.id}>
                <p className="text-lg font-bold leading-tight">
                  <span className="text-amber-400">{it.cantidad}×</span> {it.nombre}
                </p>
                {(grupos.length > 0 || libre.length > 0) && (
                  <div className="mt-1 space-y-0.5 border-l-2 border-amber-400/50 pl-2">
                    {grupos.map((g, i) => (
                      <p key={i} className="text-sm leading-snug">
                        <span className="text-white/65">{g.label}: </span>
                        <span className="font-semibold text-white">{g.val}</span>
                      </p>
                    ))}
                    {libre.map((l, i) => (
                      <p key={i} className="text-sm font-bold text-amber-300">Nota: {l}</p>
                    ))}
                  </div>
                )}
              </li>
            );
          })}
        </ul>

        {p.nota && (
          <p className="mt-2 rounded-md bg-white/5 px-2 py-1.5 text-sm font-semibold text-white/85 ring-1 ring-white/15">
            Nota: {p.nota}
          </p>
        )}

        <button
          onClick={onAvanzar}
          className="mt-3 rounded-xl py-3 text-base font-black tracking-wide text-black"
          style={{ backgroundColor: enPrep ? '#22D3EE' : '#FACC15' }}
        >
          {enPrep ? 'Marcar listo' : 'Empezar'}
        </button>
      </div>
    </article>
  );
}
