// ===== RIVAMAR Group — Panel de Administración shell (v1.1) =====
const { useState, useEffect } = React;

function KpiCard({ label, value, sub, accent, icon }) {
  return (
    <div className="bg-iron border border-white/10 rounded-xl p-5 relative overflow-hidden">
      <div className="absolute top-0 left-0 w-full h-0.5" style={{ background: accent }}></div>
      <div className="flex items-start justify-between">
        <div>
          <div className="font-display text-3xl font-bold text-gray-50">{value}</div>
          <div className="text-sm text-gray-400 mt-1">{label}</div>
        </div>
        <span className="grid place-items-center w-10 h-10 rounded-lg shrink-0" style={{ background: accent + '22', color: accent }}>{icon}</span>
      </div>
      {sub && <div className="text-xs text-gray-500 mt-3">{sub}</div>}
    </div>
  );
}

function AdminLogin({ onLogin, users }) {
  const [u, setU] = useState('admin@rivamar.cl');
  const [p, setP] = useState('');
  const [err, setErr] = useState('');
  const submit = (e) => {
    e.preventDefault();
    const lista = users || (window.storeGet ? window.storeGet().users : []);
    const found = (lista || []).find((x) => x.correo.toLowerCase() === u.trim().toLowerCase());
    if (found && found.estado === 'activo' && found.pass && found.pass === p) { setErr(''); onLogin(); }
    else if (found && found.pass && found.pass !== p) setErr('Contraseña incorrecta.');
    else if (found && found.estado !== 'activo') setErr('Usuario pendiente de activación.');
    else if (found && !found.pass) setErr('Este usuario no tiene contraseña asignada. Contacte al administrador.');
    else setErr('Correo no registrado.');
  };
  return (
    <main className="min-h-[70vh] grid place-items-center px-5 py-16">
      <form onSubmit={submit} className="w-full max-w-sm bg-iron border border-white/10 rounded-2xl p-8">
        <div className="flex justify-center mb-6"><Logo size="lg" /></div>
        <div className="text-center mb-6">
          <h1 className="font-display text-xl font-bold text-gray-50">Panel de Administración</h1>
          <p className="text-xs text-gray-500 mt-1 font-mono">admin.rivamar.cl</p>
        </div>
        <div className="space-y-4">
          <Field label="Correo corporativo"><input className={inputCls} value={u} onChange={(e) => setU(e.target.value)} /></Field>
          <Field label="Contraseña"><input type="password" className={inputCls} value={p} onChange={(e) => setP(e.target.value)} placeholder="Tu contraseña" /></Field>
          {err && <p className="text-xs text-red-400">{err}</p>}
          <Btn type="submit" variant="primary" className="w-full">Ingresar al panel</Btn>
        </div>
        <div className="mt-5 pt-4 border-t border-white/10">
          <p className="text-[11px] text-gray-500 leading-relaxed flex items-start gap-1.5">
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="shrink-0 mt-0.5"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
            <span><strong className="text-gray-400">Privacidad de datos:</strong> el acceso es exclusivo para personal autorizado de RIVAMAR Group. Toda la información de clientes y reservas se trata conforme a la <strong className="text-gray-400">Ley N° 19.628</strong> sobre protección de la vida privada. El uso indebido o acceso no autorizado queda registrado y es responsabilidad del titular de la cuenta.</span>
          </p>
          <p className="text-[10px] text-gray-600 text-center mt-3 font-mono">Demo: admin@rivamar.cl · rivamar2026 — Supabase Auth (JWT) en producción.</p>
        </div>
      </form>
    </main>
  );
}

// ---------- Dashboard ----------
function ProximasVencer({ reservas }) {
  const hoy = new Date(); hoy.setHours(0, 0, 0, 0);
  const limite = new Date(hoy); limite.setDate(limite.getDate() + 2);
  const prox = reservas.filter((r) => {
    if (r.estado === 'cancelada' || r.estado === 'eliminada') return false;
    if (!r.fecha) return false;
    const f = new Date(r.fecha + 'T00:00:00');
    return f >= hoy && f <= limite;
  }).sort((a, b) => (a.fecha + a.hora).localeCompare(b.fecha + b.hora));

  const site = (typeof window !== 'undefined' && window.SITE) || {};
  const diaTxt = (r) => {
    const f = new Date(r.fecha + 'T00:00:00'); const d = Math.round((f - new Date(new Date().setHours(0,0,0,0))) / 86400000);
    return d === 0 ? 'HOY' : d === 1 ? 'Mañana' : r.fecha;
  };
  const recordarWA = (r) => {
    const nom = LOCAL_MAP[r.local] ? LOCAL_MAP[r.local].nombre : r.local;
    const msg = `¡Hola ${r.nombre}! Le recordamos su reserva ${r.id} en ${(site.brand_nombre || 'RIVAMAR')} — ${nom} para ${r.fecha} a las ${r.hora} hrs (${r.pax} pax). ¡Le esperamos! Si necesita reagendar, responda este mensaje.`;
    const tel = (r.telefono || '').replace(/[^0-9]/g, ''); const num = tel.startsWith('56') ? tel : ('56' + tel);
    window.open(`https://wa.me/${num}?text=${encodeURIComponent(msg)}`, '_blank');
  };
  const recordarMail = (r) => {
    const nom = LOCAL_MAP[r.local] ? LOCAL_MAP[r.local].nombre : r.local;
    const body = `Hola ${r.nombre},%0D%0A%0D%0ALe recordamos su reserva ${r.id} en ${nom} para el ${r.fecha} a las ${r.hora} hrs (${r.pax} personas).%0D%0A%0D%0A¡Le esperamos!%0D%0A${(site.brand_nombre || 'RIVAMAR')} — Antofagasta`;
    window.open(`mailto:${r.correo}?subject=${encodeURIComponent('Recordatorio de su reserva ' + r.id + ' — RIVAMAR')}&body=${body}`, '_blank');
  };

  if (prox.length === 0) return null;
  return (
    <div className="bg-iron border border-gold/30 rounded-xl overflow-hidden">
      <div className="p-4 border-b border-white/10 flex items-center gap-2.5">
        <span className="grid place-items-center w-7 h-7 rounded-full bg-gold/20 text-gold shrink-0"><AdIcon name="calendar" size={15} /></span>
        <h3 className="font-display font-bold text-gray-50">Reservas próximas a vencer</h3>
        <span className="text-xs text-gray-500">({prox.length} en las próximas 48 h — recordar al cliente)</span>
      </div>
      <div className="divide-y divide-white/5">
        {prox.map((r) => (
          <div key={r.id} className="flex flex-wrap items-center gap-3 px-4 py-3 justify-between">
            <div className="min-w-0">
              <div className="flex items-center gap-2 flex-wrap">
                <span className={`text-[10px] font-bold uppercase px-2 py-0.5 rounded ${diaTxt(r) === 'HOY' ? 'bg-red-500/20 text-red-400' : 'bg-gold/15 text-gold'}`}>{diaTxt(r)}</span>
                <span className="font-medium text-gray-100">{r.nombre}</span>
                <span className="text-xs text-gray-500">{r.hora} hrs</span>
              </div>
              <p className="text-xs text-gray-500 mt-0.5">{LOCAL_MAP[r.local] ? LOCAL_MAP[r.local].nombre : r.local} · {r.pax} pax · {r.telefono}</p>
            </div>
            <div className="flex gap-2 shrink-0">
              <button onClick={() => recordarWA(r)} title="Recordar por WhatsApp" className="inline-flex items-center gap-1.5 text-xs font-semibold px-2.5 py-1.5 rounded-md bg-[#25D366]/15 text-[#25D366] hover:bg-[#25D366]/25">
                <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M17.5 14.4c-.3-.1-1.7-.8-2-.9-.3-.1-.5-.1-.6.2-.2.3-.7.9-.8 1-.2.2-.3.2-.6.1-.3-.2-1.2-.5-2.3-1.4-.9-.8-1.4-1.7-1.6-2-.2-.3 0-.5.1-.6.1-.1.3-.3.4-.5.1-.2.2-.3.3-.5.1-.2 0-.4 0-.5 0-.1-.6-1.5-.8-2-.2-.5-.4-.5-.6-.5h-.5c-.2 0-.5.1-.7.3-.2.3-.9.9-.9 2.2s.9 2.5 1.1 2.7c.1.2 1.8 2.7 4.3 3.8.6.3 1.1.4 1.5.5.6.2 1.2.2 1.6.1.5-.1 1.7-.7 1.9-1.3.2-.7.2-1.2.2-1.3-.1-.2-.3-.2-.6-.4M12 2a10 10 0 0 0-8.6 15l-1.4 5.1 5.2-1.4A10 10 0 1 0 12 2"/></svg>
                <span className="hidden sm:inline">WhatsApp</span>
              </button>
              <button onClick={() => recordarMail(r)} title="Recordar por correo" className="w-8 h-8 grid place-items-center rounded-md bg-white/5 text-gray-400 hover:text-gold">
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
              </button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function Dashboard({ reservas, onGoReservas }) {
  const total = reservas.length;
  const pendientes = reservas.filter((r) => r.estado === 'pendiente').length;
  const confirmadas = reservas.filter((r) => r.estado === 'confirmada').length;
  const exponor = reservas.filter((r) => r.exponor).length;
  const hoyStr = new Date().toISOString().slice(0, 10);
  const hoy = reservas.filter((r) => r.fecha === hoyStr).length;
  const activas = reservas.filter((r) => r.estado !== 'cancelada' && r.estado !== 'eliminada');
  const comensales = activas.reduce((s, r) => s + (Number(r.pax) || 0), 0);
  const comensalesHoy = reservas.filter((r) => r.fecha === hoyStr && r.estado !== 'cancelada' && r.estado !== 'eliminada').reduce((s, r) => s + (Number(r.pax) || 0), 0);
  const recientes = reservas.slice(0, 5);
  return (
    <div className="space-y-6">
      <div className="grid grid-cols-2 lg:grid-cols-3 gap-4">
        <KpiCard label="Total reservas" value={total} accent="#C8A000" sub="Histórico acumulado" icon={<AdIcon name="list" />} />
        <KpiCard label="Comensales (total)" value={comensales} accent="#8B5CF6" sub="Personas en reservas activas" icon={<AdIcon name="users" />} />
        <KpiCard label="Comensales hoy" value={comensalesHoy} accent="#0EA5A0" sub={`${hoy} reserva(s) · ${hoyStr}`} icon={<AdIcon name="users" />} />
        <KpiCard label="Pendientes" value={pendientes} accent="#F97316" sub="Requieren validación" icon={<AdIcon name="calendar" />} />
        <KpiCard label="Confirmadas" value={confirmadas} accent="#10B981" sub="Aforo resguardado" icon={<AdIcon name="chart" />} />
        <KpiCard label="Descuentos EXPONOR" value={exponor} accent="#F5A623" sub="Beneficio −15% aplicado" icon={<AdIcon name="star" />} />
      </div>
      <ProximasVencer reservas={reservas} />
      <div className="bg-iron border border-white/10 rounded-xl">
        <div className="p-4 border-b border-white/10 flex items-center justify-between">
          <h3 className="font-display font-bold text-gray-50">Reservas recientes</h3>
          <button onClick={onGoReservas} className="text-sm font-semibold text-gold hover:text-goldBright">Ver todas →</button>
        </div>
        <div className="divide-y divide-white/5">
          {recientes.map((r) => (
            <div key={r.id} className="flex items-center gap-4 px-4 py-3">
              <span className="font-mono text-xs text-gray-500 w-16 shrink-0">{r.id}</span>
              <div className="flex-1 min-w-0">
                <div className="text-sm font-medium text-gray-100 truncate">{r.nombre}</div>
                <div className="text-xs text-gray-500 truncate">{LOCAL_MAP[r.local].nombre} · {r.fecha} · {r.pax} pax</div>
              </div>
              {r.exponor && <span className="text-exponor text-xs font-bold shrink-0">★</span>}
              <EstadoBadge estado={r.estado} />
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ---------- Gestión de reservas ----------
function GestionReservas({ reservas, setReservas }) {
  const [query, setQuery] = useState('');
  const [filterEstado, setFilterEstado] = useState('todos');
  const [filterLocal, setFilterLocal] = useState('todos');
  const [vista, setVista] = useState('lista');
  const [editing, setEditing] = useState(null);
  const [toast, setToast] = useState('');
  const flash = (msg) => { setToast(msg); setTimeout(() => setToast(''), 2600); };

  const filtered = reservas.filter((r) => {
    if (filterEstado === 'todos') { if (r.estado === 'eliminada') return false; }
    else if (r.estado !== filterEstado) return false;
    if (filterLocal !== 'todos' && r.local !== filterLocal) return false;
    const q = query.trim().toLowerCase();
    if (q && !(`${r.nombre} ${r.empresa} ${r.id} ${r.correo} ${r.telefono}`.toLowerCase().includes(q))) return false;
    return true;
  });

  const setEstado = (id, estado) => setReservas((prev) => prev.map((r) => r.id === id ? { ...r, estado } : r));
  const eliminar = (id) => { if (confirm('¿Eliminar esta reserva? Se conservará el código correlativo y quedará marcada como "Eliminada".')) { setEstado(id, 'eliminada'); flash('Reserva eliminada (registro conservado)'); } };
  const saveEdit = (r) => {
    setReservas((prev) => {
      const existe = prev.some((x) => x.id === r.id);
      if (existe) return prev.map((x) => x.id === r.id ? r : x);
      return [{ ...r }, ...prev];
    });
    try { if (r._nueva) { delete r._nueva; window.pushToInbox && window.pushToInbox('reserva', r); } } catch (e) {}
    setEditing(null);
    flash('Reserva guardada');
  };
  const nuevaReserva = () => {
    const base = { nombre: '', empresa: '', correo: '', telefono: '', local: 'rivamar', fecha: '', hora: '', pax: 2, exponor: false, credencial: '', comentarios: '', estado: 'pendiente', _nueva: true };
    // Folio provisional inmediato; se reemplaza por el correlativo central del servidor al resolver.
    setEditing({ ...base, id: 'RV-2026-…' });
    const pedir = window.nextReservaIdAsync ? window.nextReservaIdAsync() : Promise.resolve({ id: window.nextReservaId() });
    pedir.then((res) => setEditing((cur) => (cur && cur._nueva) ? { ...cur, id: res.id } : cur));
  };

  const exportCSV = () => {
    const headers = ['id', 'nombre_completo', 'empresa', 'correo', 'telefono', 'local', 'fecha', 'hora', 'numero_personas', 'es_exponor', 'credencial', 'estado', 'comentarios'];
    const rows = filtered.map((r) => [r.id, r.nombre, r.empresa, r.correo, r.telefono, r.local, r.fecha, r.hora, r.pax, r.exponor, r.credencial || '', r.estado, r.comentarios || '']);
    const csv = [headers.join(','), ...rows.map((row) => row.map((c) => `"${String(c ?? '').replace(/"/g, '""')}"`).join(','))].join('\n');
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = `reservas_rivamar_${new Date().toISOString().slice(0, 10)}.csv`;
    document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url);
    flash(`CSV exportado · ${filtered.length} registros`);
  };

  const site = (typeof window !== 'undefined' && window.SITE) || {};
  // Comprobante PDF de la reserva (imprimible / guardar como PDF)
  const generarPDF = (r) => {
    const localNom = LOCAL_MAP[r.local] ? LOCAL_MAP[r.local].nombre : r.local;
    const estadoTxt = { pendiente: 'Pendiente', confirmada: 'Confirmada', cancelada: 'Cancelada' }[r.estado] || r.estado;
    const fila = (k, v) => `<tr><td class="k">${k}</td><td class="v">${v}</td></tr>`;
    const html = `<!doctype html><html lang="es"><head><meta charset="utf-8"><title>Reserva ${r.id}</title>
      <style>
        @media print { @page { margin: 16mm; } }
        body{font-family:Arial,Helvetica,sans-serif;color:#1C1611;margin:0;padding:34px;}
        .brand{display:flex;align-items:center;gap:12px;border-bottom:3px solid #B5552E;padding-bottom:16px}
        .logo{width:40px;height:40px;background:#B5552E;color:#fff;font-weight:800;display:grid;place-items:center;border-radius:5px;font-size:22px;font-family:Georgia,serif}
        h1{font-size:20px;margin:0} .sub{color:#8A7558;font-size:12px;margin:2px 0 0}
        .tag{display:inline-block;margin:18px 0 8px;padding:6px 14px;border-radius:99px;font-size:13px;font-weight:700}
        .pend{background:#FEF3C7;color:#B45309}.conf{background:#D1FAE5;color:#047857}.canc{background:#FEE2E2;color:#B91C1C}
        table{width:100%;border-collapse:collapse;margin-top:8px;font-size:14px}
        td{border-bottom:1px solid #EADFce;padding:10px 4px} .k{color:#8A7558;width:38%} .v{color:#1C1611;font-weight:600}
        .foot{margin-top:28px;border-top:1px solid #EADFce;padding-top:12px;color:#A08D72;font-size:11px;text-align:center}
        .exp{margin-top:14px;background:rgba(245,166,35,.12);border:1px solid rgba(245,166,35,.5);border-radius:8px;padding:10px 14px;color:#B45309;font-weight:700;font-size:13px}
      </style></head><body>
      <div class="brand"><div class="logo">R</div><div><h1>${(site.brand_nombre || 'RIVAMAR')} ${(site.brand_sub || 'GROUP')}</h1><p class="sub">Comprobante de reserva · Antofagasta, Chile</p></div></div>
      <div class="tag ${r.estado === 'confirmada' ? 'conf' : r.estado === 'cancelada' ? 'canc' : 'pend'}">Reserva ${estadoTxt}</div>
      <table>
        ${fila('Código', r.id)}
        ${fila('Local', localNom)}
        ${fila('A nombre de', r.nombre)}
        ${r.empresa ? fila('Empresa', r.empresa) : ''}
        ${fila('Fecha y hora', r.fecha + ' · ' + r.hora + ' hrs')}
        ${fila('N° de personas', r.pax + ' pax')}
        ${fila('Teléfono', r.telefono)}
        ${fila('Correo', r.correo)}
        ${r.comentarios ? fila('Comentarios', r.comentarios) : ''}
      </table>
      ${r.exponor ? '<div class="exp">★ Beneficio EXPONOR 2026 — 15% de descuento aplicado. Presente su credencial al solicitar la cuenta.</div>' : ''}
      <p class="foot">${site.footer_copy || '© 2026 RIVAMAR Group — Antofagasta, Chile · MAEDY GROUP'}<br/>Documento generado desde el panel de administración.</p>
      <script>window.onload=function(){setTimeout(function(){window.print()},350)}<\/script>
      </body></html>`;
    const w = window.open('', '_blank');
    if (w) { w.document.write(html); w.document.close(); }
    flash('Comprobante PDF generado · ' + r.id);
  };

  // Envío rápido por WhatsApp al cliente con el detalle de la reserva
  const enviarWhatsApp = (r) => {
    const localNom = LOCAL_MAP[r.local] ? LOCAL_MAP[r.local].nombre : r.local;
    const estadoTxt = { pendiente: 'Pendiente de confirmación', confirmada: 'CONFIRMADA ✅', cancelada: 'Cancelada' }[r.estado] || r.estado;
    const msg = [
      `¡Hola ${r.nombre}! 👋`,
      ``,
      `Tu reserva en *${(site.brand_nombre || 'RIVAMAR')} — ${localNom}*:`,
      `📋 Código: ${r.id}`,
      `📅 Fecha: ${r.fecha} a las ${r.hora} hrs`,
      `👥 Personas: ${r.pax}`,
      r.exponor ? `⭐ Beneficio EXPONOR 2026: 15% de descuento` : '',
      `📌 Estado: ${estadoTxt}`,
      ``,
      `¡Te esperamos! Cualquier cambio, responde este mensaje.`,
    ].filter(Boolean).join('\n');
    const tel = (r.telefono || '').replace(/[^0-9]/g, '');
    const num = tel.startsWith('56') ? tel : ('56' + tel.replace(/^0+/, ''));
    window.open(`https://wa.me/${num}?text=${encodeURIComponent(msg)}`, '_blank');
  };

  const pillCls = (active) => `px-3 py-1.5 rounded-md text-xs font-medium transition-colors min-h-[36px] ${active ? 'bg-gold text-carbon' : 'bg-carbon border border-white/10 text-gray-400 hover:text-gray-100'}`;
  const vistaBtn = (v, icon, label) => (
    <button onClick={() => setVista(v)} className={`flex items-center gap-1.5 px-3 min-h-[36px] rounded-md text-xs font-medium ${vista === v ? 'bg-white/10 text-gold' : 'text-gray-400 hover:text-gray-100'}`}>
      <AdIcon name={icon} size={14} /> {label}
    </button>
  );

  return (
    <div className="bg-iron border border-white/10 rounded-xl">
      <div className="p-4 border-b border-white/10 flex flex-col lg:flex-row gap-3 lg:items-center justify-between">
        <div className="relative flex-1 max-w-sm">
          <span className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500"><AdIcon name="list" size={15} /></span>
          <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Buscar por nombre, empresa, teléfono, ID…"
            className="w-full min-h-[40px] pl-9 pr-3 rounded-md bg-carbon border border-white/10 text-gray-100 text-sm placeholder-gray-600 focus:border-gold outline-none" />
        </div>
        <div className="flex flex-wrap items-center gap-2">
          <div className="flex items-center gap-1 bg-carbon border border-white/10 rounded-md p-0.5">
            {vistaBtn('lista', 'list', 'Lista')}
            {vistaBtn('calendario', 'calendar', 'Calendario')}
          </div>
          <Btn variant="primary" onClick={nuevaReserva} className="!min-h-[36px] !px-3 !text-xs">+ Nueva reserva</Btn>
          <Btn variant="outline" onClick={exportCSV} className="!min-h-[36px] !px-3 !text-xs">Exportar CSV</Btn>
        </div>
      </div>

      {vista === 'lista' && (
        <>
          <div className="px-4 py-3 border-b border-white/10 flex flex-wrap items-center gap-2">
            {[['todos','Activas'],['pendiente','Pendientes'],['confirmada','Confirmadas'],['cancelada','Canceladas'],['eliminada','Eliminadas']].map(([id,l]) => (
              <button key={id} className={pillCls(filterEstado === id)} onClick={() => setFilterEstado(id)}>{l}</button>
            ))}
            <span className="w-px h-5 bg-white/10 mx-1"></span>
            <select value={filterLocal} onChange={(e) => setFilterLocal(e.target.value)} className="min-h-[36px] px-2.5 rounded-md bg-carbon border border-white/10 text-gray-300 text-xs">
              <option value="todos">Todos los locales</option>
              {LOCALES.map((l) => <option key={l.id} value={l.id}>{l.nombre}</option>)}
            </select>
          </div>

          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="text-left text-xs uppercase tracking-wider text-gray-500 border-b border-white/10">
                  <th className="px-4 py-3 font-semibold">ID</th>
                  <th className="px-4 py-3 font-semibold">Cliente / Empresa</th>
                  <th className="px-4 py-3 font-semibold">Local</th>
                  <th className="px-4 py-3 font-semibold">Fecha</th>
                  <th className="px-4 py-3 font-semibold text-center">Pax</th>
                  <th className="px-4 py-3 font-semibold">EXPONOR</th>
                  <th className="px-4 py-3 font-semibold">Estado</th>
                  <th className="px-4 py-3 font-semibold text-right">Acciones</th>
                </tr>
              </thead>
              <tbody>
                {filtered.map((r) => (
                  <tr key={r.id} className="border-b border-white/5 hover:bg-white/[0.02]">
                    <td className="px-4 py-3 font-mono text-xs text-gray-400">{r.id}</td>
                    <td className="px-4 py-3">
                      <div className="font-medium text-gray-100">{r.nombre}</div>
                      <div className="text-xs text-gray-500">{r.empresa || 'Particular'}</div>
                    </td>
                    <td className="px-4 py-3 text-gray-300">{LOCAL_MAP[r.local].nombre}</td>
                    <td className="px-4 py-3 text-gray-400 whitespace-nowrap">{r.fecha}<span className="text-gray-600"> · {r.hora}</span></td>
                    <td className="px-4 py-3 text-center text-gray-300">{r.pax}</td>
                    <td className="px-4 py-3">{r.exponor ? <span className="text-exponor text-xs font-bold">★ −15%</span> : <span className="text-gray-600">—</span>}</td>
                    <td className="px-4 py-3"><EstadoBadge estado={r.estado} /></td>
                    <td className="px-4 py-3">
                      <div className="flex items-center justify-end gap-1.5">
                        {r.estado !== 'confirmada' && <button onClick={() => setEstado(r.id, 'confirmada')} className="text-[11px] font-semibold px-2 py-1.5 rounded-md bg-emerald-500/15 text-emerald-400 hover:bg-emerald-500/25 whitespace-nowrap">✓ Confirmar</button>}
                        {r.estado !== 'cancelada' && <button onClick={() => setEstado(r.id, 'cancelada')} className="text-[11px] font-semibold px-2 py-1.5 rounded-md bg-red-500/10 text-red-400 hover:bg-red-500/20 whitespace-nowrap">Cancelar</button>}
                        {r.estado === 'cancelada' && <button onClick={() => setEstado(r.id, 'pendiente')} className="text-[11px] font-semibold px-2 py-1.5 rounded-md bg-white/5 text-gray-400 hover:bg-white/10 whitespace-nowrap">↺ Reabrir</button>}
                        {r.estado === 'eliminada' && <button onClick={() => setEstado(r.id, 'pendiente')} className="text-[11px] font-semibold px-2 py-1.5 rounded-md bg-emerald-500/15 text-emerald-400 hover:bg-emerald-500/25 whitespace-nowrap">↺ Restaurar</button>}
                        <button onClick={() => enviarWhatsApp(r)} title="Enviar al cliente por WhatsApp" className="w-8 h-8 grid place-items-center rounded-md bg-[#25D366]/15 text-[#25D366] hover:bg-[#25D366]/25">
                          <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M17.5 14.4c-.3-.1-1.7-.8-2-.9-.3-.1-.5-.1-.6.2-.2.3-.7.9-.8 1-.2.2-.3.2-.6.1-.3-.2-1.2-.5-2.3-1.4-.9-.8-1.4-1.7-1.6-2-.2-.3 0-.5.1-.6.1-.1.3-.3.4-.5.1-.2.2-.3.3-.5.1-.2 0-.4 0-.5 0-.1-.6-1.5-.8-2-.2-.5-.4-.5-.6-.5h-.5c-.2 0-.5.1-.7.3-.2.3-.9.9-.9 2.2s.9 2.5 1.1 2.7c.1.2 1.8 2.7 4.3 3.8.6.3 1.1.4 1.5.5.6.2 1.2.2 1.6.1.5-.1 1.7-.7 1.9-1.3.2-.7.2-1.2.2-1.3-.1-.2-.3-.2-.6-.4M12 2a10 10 0 0 0-8.6 15l-1.4 5.1 5.2-1.4A10 10 0 1 0 12 2"/></svg>
                        </button>
                        <button onClick={() => generarPDF(r)} title="Descargar comprobante PDF" className="w-8 h-8 grid place-items-center rounded-md bg-white/5 text-gray-400 hover:text-gold">
                          <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><polyline points="9 15 12 18 15 15"/></svg>
                        </button>
                        <button onClick={() => setEditing(r)} title="Editar" className="w-8 h-8 grid place-items-center rounded-md bg-white/5 text-gray-400 hover:text-gold"><AdIcon name="edit" size={14} /></button>
                        {r.estado !== 'eliminada' && <button onClick={() => eliminar(r.id)} title="Eliminar reserva" className="w-8 h-8 grid place-items-center rounded-md bg-red-500/10 text-red-400 hover:bg-red-500/20"><AdIcon name="trash" size={14} /></button>}
                      </div>
                    </td>
                  </tr>
                ))}
                {filtered.length === 0 && <tr><td colSpan="8" className="px-4 py-12 text-center text-gray-500">No hay reservas que coincidan con los filtros.</td></tr>}
              </tbody>
            </table>
          </div>
          <div className="px-4 py-3 border-t border-white/10 text-xs text-gray-500 flex justify-between">
            <span>Mostrando {filtered.length} de {reservas.length} reservas</span>
            <span className="font-mono">tabla: reservas · PostgreSQL</span>
          </div>
        </>
      )}

      {vista === 'calendario' && <CalendarView reservas={reservas} onSelect={(r) => setEditing(r)} />}

      {editing && <EditModal reserva={editing} onSave={saveEdit} onClose={() => setEditing(null)} />}
      {toast && <div className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 bg-emerald-600 text-white text-sm font-medium px-5 py-3 rounded-lg shadow-xl">{toast}</div>}
    </div>
  );
}

// ---------- Shell con sidebar ----------
function AdminShell({ reservas, setReservas, users, setUsers, galeria, setGaleria, cotizaciones, setCotizaciones, content, setContent, resetContent, go, onLogout }) {
  const [section, setSection] = useState('dashboard');
  const [pubMsg, setPubMsg] = useState('');
  const [pubBusy, setPubBusy] = useState(false);
  const [pend, setPend] = useState(false);
  useEffect(() => {
    const tick = () => { try { setPend(!!(window.hasPendingChanges && window.hasPendingChanges())); } catch (e) {} };
    tick();
    const iv = setInterval(tick, 2500);
    return () => clearInterval(iv);
  }, []);
  const publicar = () => {
    setPubBusy(true); setPubMsg('');
    window.publishToServer().then((r) => {
      setPubBusy(false);
      if (r.ok) setPubMsg('✓ Publicado en el servidor — visible en todos los dispositivos');
      else setPubMsg('No se pudo publicar (' + r.error + '). Verifica que api/data.php esté subido.');
      setTimeout(() => setPubMsg(''), 5000);
    });
  };
  const nav = [
    ['dashboard', 'Dashboard', 'home'],
    ['reservas', 'Gestión de Reservas', 'list'],
    ['galeria', 'Galería Admin', 'image'],
    ['cms', 'CMS Lite', 'edit'],
    ['cotizaciones', 'Cotizaciones B2B', 'briefcase'],
    ['correos', 'Correos', 'mail'],
    ['usuarios', 'Usuarios', 'users'],
    ['visitas', 'Visitas', 'globe'],
    ['reportes', 'Reportes', 'chart'],
    ['manual', 'Manual de Usuario', 'book'],
  ];
  const titles = {
    dashboard: ['Dashboard', 'Resumen general de reservas'],
    cotizaciones: ['Cotizaciones B2B', 'Solicitudes de convenio de empresas'],
    reservas: ['Gestión de Reservas', 'Listado, calendario y exportación'],
    galeria: ['Galería Admin', 'Gestor de archivos multimedia'],
    cms: ['CMS Lite', 'Edición de contenido del sitio'],
    correos: ['Correos', 'Plantillas branded de notificación'],
    usuarios: ['Usuarios', 'Control de accesos y roles'],
    visitas: ['Visitas', 'Analítica de tráfico e IP de visitantes'],
    reportes: ['Reportes', 'Métricas de reservas por periodo y local'],
    manual: ['Manual de Usuario', 'Guía interactiva del sistema'],
  };
  const [mobNav, setMobNav] = useState(false);

  return (
    <div className="flex min-h-screen bg-carbon">
      {/* Sidebar */}
      <aside className={`fixed lg:static z-40 inset-y-0 left-0 w-60 border-r border-white/10 bg-steel p-5 shrink-0 flex flex-col transition-transform ${mobNav ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}`}>
        <Logo onClick={() => go('home')} />
        <nav className="mt-8 space-y-1 flex-1">
          {nav.map(([id, label, icon]) => (
            <button key={id} onClick={() => { setSection(id); setMobNav(false); }}
              className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm font-medium transition-colors ${section === id ? 'bg-gold/15 text-gold' : 'text-gray-400 hover:text-gray-100 hover:bg-white/5'}`}>
              <AdIcon name={icon} size={17} /> {label}
            </button>
          ))}
        </nav>
        <button onClick={() => go('home')} className="text-sm text-gray-400 hover:text-gray-100 flex items-center gap-2 px-3 py-2">← Salir al sitio</button>
      </aside>
      {mobNav && <div className="fixed inset-0 z-30 bg-black/50 lg:hidden" onClick={() => setMobNav(false)}></div>}

      {/* Main */}
      <div className="flex-1 min-w-0">
        <header className="border-b border-white/10 px-5 lg:px-8 h-16 flex items-center justify-between gap-3">
          <div className="flex items-center gap-3 min-w-0">
            <button className="lg:hidden text-gray-300 p-1" onClick={() => setMobNav(true)}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
            </button>
            <div className="min-w-0">
              <h1 className="font-display font-bold text-gray-50 text-lg leading-none truncate">{titles[section][0]}</h1>
              <p className="text-xs text-gray-500 mt-0.5 truncate">{titles[section][1]}</p>
            </div>
          </div>
          <div className="flex items-center gap-3 shrink-0">
            <button onClick={publicar} disabled={pubBusy} title="Publicar cambios en el servidor (todos los dispositivos)" className={`relative inline-flex items-center gap-1.5 text-xs font-semibold px-3 py-2 rounded-md min-h-[40px] disabled:opacity-50 ${pend ? 'bg-gold text-carbon animate-pulse-soft' : 'bg-gold/15 text-gold hover:bg-gold/25'}`}>
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/></svg>
              <span className="hidden sm:inline">{pubBusy ? 'Publicando…' : (pend ? 'Publicar cambios pendientes' : 'Publicar al servidor')}</span>
              {pend && <span className="absolute -top-1 -right-1 flex h-3 w-3"><span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-red-400 opacity-75"></span><span className="relative inline-flex rounded-full h-3 w-3 bg-red-500"></span></span>}
            </button>
            <button onClick={() => {
              if (window.hasPendingChanges && window.hasPendingChanges()) {
                alert('⚠ USTED TIENE INFORMACIÓN PENDIENTE DE PUBLICAR AL SERVIDOR.\n\nPrimero pulse «Publicar al servidor» para que las reservas y cambios queden guardados en todos los dispositivos, y LUEGO CIERRE LA SESIÓN.');
                return;
              }
              if (confirm('¿Cerrar sesión? Asegúrese de haber publicado los cambios al servidor.')) onLogout();
            }} title="Cerrar sesión" className="inline-flex items-center gap-1.5 text-xs font-semibold px-3 py-2 rounded-md bg-red-500/10 text-red-400 hover:bg-red-500/20 min-h-[40px]">
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
              <span className="hidden sm:inline">Cerrar sesión</span>
            </button>
          </div>
        </header>
        {pubMsg && <div className="px-5 lg:px-8 py-2.5 bg-gold/10 border-b border-gold/20 text-xs text-gold">{pubMsg}</div>}

        <div className="p-5 lg:p-8">
          {section === 'dashboard' && <Dashboard reservas={reservas} onGoReservas={() => setSection('reservas')} />}
          {section === 'reservas' && <GestionReservas reservas={reservas} setReservas={setReservas} />}
          {section === 'galeria' && <GaleriaAdmin galeria={galeria} setGaleria={setGaleria} />}
          {section === 'cms' && <CmsLite content={content} setContent={setContent} resetContent={resetContent} onVerSitio={() => go('home')} />}
          {section === 'cotizaciones' && <Cotizaciones cotizaciones={cotizaciones} setCotizaciones={setCotizaciones} />}
          {section === 'correos' && <Correos reservas={reservas} cotizaciones={cotizaciones} setReservas={setReservas} />}
          {section === 'usuarios' && <Usuarios users={users} setUsers={setUsers} />}
          {section === 'visitas' && <Visitas />}
          {section === 'reportes' && <Reportes reservas={reservas} />}
          {section === 'manual' && <Manual />}
        </div>
      </div>
    </div>
  );
}

function Admin(props) {
  const [authed, setAuthed] = useState(props.authed);
  useEffect(() => { if (props.authed) setAuthed(true); }, [props.authed]);
  const onLogin = () => { setAuthed(true); props.onAuthed && props.onAuthed(); };
  return authed ? <AdminShell {...props} /> : <AdminLogin onLogin={onLogin} users={props.users} />;
}

Object.assign(window, { Admin });
