// ===== RIVAMAR Group — Store central + contenido editable (v4) =====
// Fuente única de verdad: persiste en localStorage y alimenta tanto el sitio
// público como el panel admin. Todo el contenido es editable desde el CMS.

const { useSyncExternalStore } = React;

// ---------- Reglas de negocio (fijas, Sec. 5.6) ----------
const CAPACIDAD = { costanera: 60, inca: 40, rivamar: 100 };
const MINIMO = { costanera: 1, inca: 1, rivamar: 10 };
const HORARIOS = ['12:30', '13:00', '13:30', '14:00', '20:00', '20:30', '21:00', '21:30'];
const EXPONOR_CODE = 'EXPONOR15';
const EXPONOR_DCTO = 0.15;
const EXPONOR_INICIO = '2026-06-08';
const CAT_LABEL = { plato: 'Plato', ambiente: 'Ambiente', evento: 'Evento', bebida: 'Bebida', buffet: 'Buffet' };

// Helper de fotos reales (stock libre de derechos · Unsplash)
const IMG = (id, w = 1200) => `https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=${w}&q=80`;

// ---------- Contenido por defecto (editable) ----------
const DEFAULT_LOCALES = [
  {
    id: 'costanera', slug: 'aromas-costanera', nombre: 'Aromas Costanera',
    tagline: 'Alta cocina de autor',
    especialidad: 'Alta cocina de autor · Breakfast & Lunch · Bar · Experiencia gourmet frente al Pacífico.',
    descripcion: 'En el sector costanero de Antofagasta, Aromas Costanera ofrece una experiencia gourmet de autor: desayunos, almuerzos y bar. Cocina contemporánea, productos frescos del norte y coctelería premium en un ambiente elegante con vista al mar — el punto de encuentro de ejecutivos y delegaciones del sector minero.',
    web: 'www.aromascostanera.cl',
    ubicacion: 'Av. Costanera 1420, Antofagasta', horario: 'Lun a Sáb · 12:30 – 23:00 hrs', telefono: '+56 55 245 1420',
    perfil: 'Ejecutivos · delegaciones · público gourmet',
    destacados: ['Cocina de autor', 'Breakfast & Lunch', 'Bar & coctelería'],
    menu: [
      { plato: 'Ceviche Clásico Costanera', desc: 'Pescado del día, leche de tigre, camote, choclo peruano', precio: '$14.900' },
      { plato: 'Tiradito Nikkei', desc: 'Láminas de pescado, crema de ají amarillo, leche de tigre nikkei', precio: '$13.500' },
      { plato: 'Arroz con Mariscos', desc: 'Arroz meloso, mariscos de la zona, culantro y ají panca', precio: '$16.900' },
      { plato: 'Pisco Sour Premium', desc: 'Pisco quebranta, limón de pica, jarabe de goma', precio: '$6.500' },
    ],
    capacidad: 60, capacidadLabel: 'Hasta 60 pax', tono: '#C9A24B', foto: 'Salón Costanera — ambiente gourmet con vista al mar', foto_img: IMG('1467003909585-2f8a72700288', 1400),
    mapa: 'Av. Costanera 1420, Antofagasta, Chile',
  },
  {
    id: 'inca', slug: 'aromas-del-inca', nombre: 'Aromas del Inca',
    tagline: 'Carnes a la piedra volcánica',
    especialidad: 'Especialidad en carnes a la piedra volcánica, cocina natural y fusión ancestral.',
    descripcion: 'Aromas del Inca es santuario de la carne premium cocida sobre piedra volcánica al centro de la mesa. Cocina natural y fusión ancestral andina, cortes Angus Premium y guisos de altura en un espacio cálido de piedra y barro — ideal para almuerzos de negocios y celebraciones.',
    web: 'www.aromasdelinca.cl',
    ubicacion: 'Calle Prat 765, Antofagasta', horario: 'Lun a Dom · 12:00 – 22:30 hrs', telefono: '+56 55 245 0765',
    perfil: 'Almuerzos de negocios · celebraciones · familias',
    destacados: ['Carnes a la piedra', 'Angus Premium', 'Fusión ancestral'],
    menu: [
      { plato: 'Angus Premium a la Piedra Volcánica', desc: 'Corte premium sellado sobre piedra al centro de la mesa, trío de salsas', precio: '$18.900' },
      { plato: 'Lomo Saltado Andino', desc: 'Lomo de res al wok, cebolla morada, tomate, papas, arroz', precio: '$13.900' },
      { plato: 'Picarones de la Casa', desc: 'Buñuelos de zapallo y camote, miel de chancaca', precio: '$5.900' },
      { plato: 'Arroz con Leche', desc: 'Receta tradicional, canela y cáscara de naranja', precio: '$4.900' },
    ],
    capacidad: 40, capacidadLabel: 'Hasta 40 pax', tono: '#6E8CAE', foto: 'Comedor del Inca — carnes a la piedra volcánica', foto_img: IMG('1432139555190-58524dae6a55', 1400),
    mapa: 'Calle Prat 765, Antofagasta, Chile',
  },
  {
    id: 'rivamar', slug: 'rivamar', nombre: 'Rivamar',
    tagline: 'Sazón donde te encuentres',
    especialidad: 'Alimentación masiva e industrial para faenas, campamentos y zonas mineras de la región.',
    descripcion: 'El local matriz e histórico de la marca. Rivamar es la casa de la alimentación masiva e industrial: servicio para faenas, campamentos y zonas mineras de la región, además de banquetes y catering corporativo. Sazón donde te encuentres — capacidad para delegaciones de 10 a más de 50 personas.',
    web: 'www.rivamar.cl',
    ubicacion: 'Av. Pedro Aguirre Cerda 5200, Antofagasta', horario: 'Lun a Dom · 12:00 – 23:30 hrs', telefono: '+56 55 245 5200',
    perfil: 'Faenas · campamentos · banquetes corporativos',
    destacados: ['Alimentación industrial', 'Catering de faena', 'Buffet masivo'],
    menu: [
      { plato: 'Causa Limeña Estructurada', desc: 'Papa amarilla prensada, palta, pollo o atún, salsa golf', precio: '$10.900' },
      { plato: 'Parrillada Marina Rivamar', desc: 'Pescados y mariscos a la parrilla, para compartir', precio: '$32.900' },
      { plato: 'Buffet Corporativo Minero', desc: 'Estación completa fría y caliente · por persona (min. 20 pax)', precio: '$18.500' },
      { plato: 'Chupe de Camarones', desc: 'Crema marina norteña, camarones, queso, huevo pochado', precio: '$15.900' },
    ],
    capacidad: 100, capacidadLabel: 'Hasta 100 pax', tono: '#3E8C84', foto: 'Salón matriz Rivamar — servicio masivo e industrial', foto_img: IMG('1414235077428-338989a2e8c0', 1400),
    mapa: 'Av. Pedro Aguirre Cerda 5200, Antofagasta, Chile',
  },
];

const DEFAULT_GALERIA = [
  { id: 1, local: 'costanera', cat: 'plato',    destacada: true,  label: 'Ceviche clásico emplatado',     img: IMG('1467003909585-2f8a72700288') },
  { id: 2, local: 'costanera', cat: 'ambiente', destacada: false, label: 'Salón con vista al mar',          img: IMG('1517248135467-4c7edcad34c4') },
  { id: 3, local: 'costanera', cat: 'bebida',   destacada: false, label: 'Coctelería de autor',            img: IMG('1424847651672-bf20a4b0982b') },
  { id: 4, local: 'inca',      cat: 'plato',    destacada: true,  label: 'Carne a la piedra volcánica',    img: IMG('1432139555190-58524dae6a55') },
  { id: 5, local: 'inca',      cat: 'ambiente', destacada: false, label: 'Mesa servida tradición andina',  img: IMG('1414235077428-338989a2e8c0') },
  { id: 6, local: 'inca',      cat: 'plato',    destacada: false, label: 'Corte Angus Premium',            img: IMG('1481931098730-318b6f776db0') },
  { id: 7, local: 'rivamar',   cat: 'buffet',   destacada: true,  label: 'Estación de buffet corporativo', img: IMG('1504674900247-0877df9cc836') },
  { id: 8, local: 'rivamar',   cat: 'evento',   destacada: true,  label: 'Banquete de cierre minero',      img: IMG('1600891964599-f61ba0e24092') },
  { id: 9, local: 'rivamar',   cat: 'plato',    destacada: false, label: 'Parrillada para compartir',      img: IMG('1555939594-58d7cb561ad1') },
  { id: 10, local: 'costanera', cat: 'plato',   destacada: false, label: 'Plato de autor',                 img: IMG('1559737558-2f5a35f4523b') },
  { id: 11, local: 'rivamar',  cat: 'ambiente', destacada: false, label: 'Montaje de salón amplio',        img: IMG('1466637574441-749b8f19452f') },
  { id: 12, local: 'inca',     cat: 'bebida',   destacada: false, label: 'Bebida de la casa',              img: IMG('1559054663-e8d23213f55c') },
];

const DEFAULT_STATS = [
  { n: 19, suf: '+', label: 'años de trayectoria' },
  { n: 3, suf: '', label: 'locales de autor' },
  { n: 120, suf: '+', label: 'empresas atendidas' },
  { n: 850, suf: 'K', label: 'platos servidos' },
];

const DEFAULT_SITE = {
  hero_titulo: 'Gastronomía de alto estándar para la industria minera',
  hero_subtitulo: '+19 años alimentando al corazón minero del país',
  hero_cuerpo: 'Calidad, tradición andina y servicio masivo para el corazón minero del país. Tres experiencias, un mismo estándar de excelencia.',
  hero_img: IMG('1414235077428-338989a2e8c0', 1900),
  hero_img2: IMG('1517248135467-4c7edcad34c4', 1900),
  hero_img3: IMG('1600891964599-f61ba0e24092', 1900),
  hero_blur: 1,
  hero_overlay: 60,
  banner_exponor: 'Presente su credencial de asistente, visitante, expositor, proveedor o trabajador de EXPONOR CHILE 2026 (8 al 11 de junio) y obtenga un 15% de descuento durante todo junio en cualquiera de nuestros locales.',
  contacto_correo: 'contacto@rivamar.cl',
  contacto_telefono: '+56 9 6497 9087',
  whatsapp: '56964979087',
  theme: 'midnight',
  local_blur: 1,
  local_overlay: 60,
  footer_desc: '+19 años de gastronomía de alto estándar para la industria minera. Tradición andina, cocina marina y servicio B2B integral para el corazón industrial del país.',
  footer_copy: '© 2026 RIVAMAR Group — Antofagasta, Chile · MAEDY GROUP',
  social_ig: 'https://www.rivamar.cl',
  social_fb: 'https://www.rivamar.cl',
  social_in: 'https://www.rivamar.cl',
  email_auto: false,
  email_modo: 'php',
  emailjs_public: '',
  emailjs_service: '',
  emailjs_template: '',
  email_destino: 'contacto@rivamar.cl',
  notify_wa: false,
  callmebot_phone: '+56964979087',
  callmebot_apikey: '',
  brand_nombre: 'RIVAMAR',
  brand_sub: 'GROUP',
  brand_inicial: 'R',
  logo_img: '',
  mch_url: 'https://www.mch.cl/',
  mch_titulo: 'Aparecemos en la Revista Oficial de la Minería Chilena',
  mch_eyebrow: 'Prensa minera oficial',
  mch_texto: 'Conoce la cobertura de EXPONOR 2026 y descubre por qué las principales empresas mineras del país eligen a RIVAMAR Group. Lee la edición oficial en Minería Chilena (MCH).',
  mch_boton: 'Ver revista oficial',
  pillars: [
    ['+19 años', 'de experiencia'],
    ['Servicios B2B', 'especializados'],
    ['360° servicio', 'gastronómico integral'],
  ],
  valores_footer: [
    ['Seguridad y cumplimiento', 'Estándares reconocidos'],
    ['Productos locales y sostenibles', 'Apoyo a la economía regional'],
    ['Flexibilidad y escalabilidad', 'Soluciones a la medida'],
  ],
};

const DEFAULT_NOSOTROS = {
  intro: 'RIVAMAR Group nació en Antofagasta con una convicción: la industria minera merece gastronomía de alto estándar. Hoy operamos tres experiencias de autor bajo un mismo compromiso de calidad, tradición y servicio.',
  blur: 1,
  overlay: 60,
  img: IMG('1559339352-11d035aa65de', 1900),
  equipo_img: IMG('1577219491135-ce391730fb2c', 1200),
  valores: [
    ['Alto estándar', 'Cocina premium y servicio impecable, sin importar el tamaño del grupo.'],
    ['Tradición', 'Recetas andinas y marinas del norte de Chile, mantenidas por +19 años.'],
    ['Servicio B2B', 'Operación masiva y eficiente diseñada para el ritmo de la gran minería.'],
    ['Cercanía', 'Atención personalizada para ejecutivos, delegaciones y familias.'],
  ],
  hitos: [
    ['2007', 'Nace Rivamar (Gran Chimú), local matriz de cocina marina norteña.'],
    ['2013', 'Apertura de Aromas del Inca, cocina andina en el interior de la ciudad.'],
    ['2018', 'Aromas Costanera suma la cocina peruana de autor frente al mar.'],
    ['2026', 'Plataforma digital unificada y convenios para EXPONOR 2026.'],
  ],
  equipo: [
    ['Dirección General', 'MAEDY GROUP', 'Estrategia y operación del holding gastronómico.', IMG('1577219491135-ce391730fb2c', 1000)],
    ['Chef Ejecutivo', 'Cocina de autor', 'Lidera la propuesta culinaria de los tres locales.', IMG('1583394293214-28a5b42c1c8a', 1000)],
    ['Gerencia de Convenios', 'Ventas B2B', 'Atiende contratos corporativos y delegaciones mineras.', IMG('1573497019940-1c28c88b4f3e', 1000)],
  ],
};

const DEFAULT_CONVENIOS = {
  intro: 'Servicio B2B masivo y eficiente diseñado para el corazón industrial del país. Convenios de alimentación con precios especiales, facturación mensual y atención personalizada.',
  img: IMG('1414235077428-338989a2e8c0', 1400),
  img2: IMG('1504674900247-0877df9cc836', 1600),
  beneficios: [
    ['Facturación mensual', 'Convenios corporativos con cobro consolidado.'],
    ['Reservas masivas', 'Delegaciones de 20 a 50+ personas para ferias industriales.'],
    ['Salones privados', 'Buffet ejecutivo y catering industrial de alto estándar.'],
  ],
};

const DEFAULT_RESERVAS = [
  { id: 'RV-2026-2102', nombre: 'Ignacio Tapia',    empresa: 'Codelco Norte', correo: 'itapia@codelco.cl',    telefono: '+56 9 7712 0098', local: 'costanera', fecha: '2026-06-09', hora: '20:30', pax: 8,  exponor: true,  credencial: 'EXP-38104', comentarios: 'Cena ejecutiva', estado: 'confirmada' },
  { id: 'RV-2026-2101', nombre: 'María José Rivas',  empresa: '',              correo: 'mj.rivas@gmail.com',   telefono: '+56 9 6650 1187', local: 'inca',      fecha: '2026-06-10', hora: '13:30', pax: 4,  exponor: false, credencial: '', comentarios: 'Una persona celíaca', estado: 'pendiente'  },
  { id: 'RV-2026-2100', nombre: 'Rodrigo Salazar',  empresa: 'Antofagasta Minerals', correo: 'rsalazar@aminerals.cl', telefono: '+56 9 5540 8821', local: 'rivamar', fecha: '2026-06-11', hora: '21:00', pax: 24, exponor: true,  credencial: 'EXP-50271', comentarios: 'Cena de cierre de faena', estado: 'pendiente' },
];
const RESERVA_SEQ = 2103; // próximo correlativo (las nuevas reservas continúan desde aquí)

const DEFAULT_USERS_LEGACY_REMOVED = null;
// Módulos del panel y roles (asignación de permisos)
const ADMIN_MODULOS = [
  ['dashboard', 'Dashboard'], ['reservas', 'Gestión de Reservas'], ['cotizaciones', 'Cotizaciones B2B'], ['galeria', 'Galería Admin'],
  ['cms', 'CMS Lite'], ['correos', 'Correos'], ['usuarios', 'Usuarios'], ['visitas', 'Visitas'], ['reportes', 'Reportes'],
];
const ROLES = {
  'Administrador':   { modulos: ADMIN_MODULOS.map((m) => m[0]), desc: 'Acceso total al sistema' },
  'Encargado Local': { modulos: ['dashboard', 'reservas', 'cotizaciones', 'galeria', 'correos', 'reportes'], desc: 'Opera reservas y contenido de su local' },
  'Usuario básico':  { modulos: ['dashboard', 'reservas'], desc: 'Solo consulta y gestión de reservas' },
};

const DEFAULT_USERS = [
  { id: 1, nombre: 'Admin Rivamar',   correo: 'admin@rivamar.cl',     pass: 'rivamar2026', rol: 'Administrador',   ultima: '2026-05-29 09:14', estado: 'activo',    modulos: ROLES['Administrador'].modulos.slice() },
  { id: 2, nombre: 'Lorena Vega',     correo: 'l.vega@rivamar.cl',    pass: 'lorena2026',  rol: 'Encargado Local', ultima: '2026-05-28 18:40', estado: 'activo',    modulos: ROLES['Encargado Local'].modulos.slice() },
  { id: 3, nombre: 'Marco Pizarro',   correo: 'm.pizarro@rivamar.cl', pass: 'marco2026',   rol: 'Usuario básico',  ultima: '2026-05-27 12:05', estado: 'activo',    modulos: ROLES['Usuario básico'].modulos.slice() },
  { id: 4, nombre: 'Invitado Ventas', correo: 'ventas@rivamar.cl',    pass: '',            rol: 'Usuario básico',  ultima: '—',                estado: 'pendiente', modulos: ROLES['Usuario básico'].modulos.slice() },
];

const DEFAULT_EXPONOR = {
  img: IMG('1600891964599-f61ba0e24092', 1900),
  img2: IMG('1517248135467-4c7edcad34c4', 1900),
  img3: IMG('1414235077428-338989a2e8c0', 1900),
  blur: 1,
  overlay: 60,
  titulo: 'EXPONOR CHILE 2026',
  subtitulo: '8 al 11 de junio · Antofagasta, Chile',
  cuerpo: 'Durante la feria minera más importante de Latinoamérica, RIVAMAR Group ofrece un 15% de descuento a toda la comunidad de EXPONOR — durante todo junio 2026.',
  fecha_evento: '2026-06-08',
};

function buildDefaults() {
  return {
    locales: DEFAULT_LOCALES,
    galeria: DEFAULT_GALERIA,
    stats: DEFAULT_STATS,
    site: DEFAULT_SITE,
    nosotros: DEFAULT_NOSOTROS,
    convenios: DEFAULT_CONVENIOS,
    exponor: DEFAULT_EXPONOR,
    reservas: DEFAULT_RESERVAS,
    reservaSeq: RESERVA_SEQ,
    cotizaciones: [],
    users: DEFAULT_USERS,
  };
}

// ---------- Folio de reserva ----------
// IMPORTANTE (concurrencia): el número correlativo NO debe generarse en el
// dispositivo. Cada navegador tenía su propio contador local y dos teléfonos
// distintos producían el MISMO id (RV-2026-2103), que luego la bandeja del
// servidor descartaba como "duplicado" → la reserva se perdía. Por eso el
// folio ahora se pide al servidor (api/reserva-id.php), que lo entrega de
// forma atómica y estrictamente ascendente.

// Respaldo SOLO si no hay servidor (preview/sandbox u offline). Genera un folio
// provisional ÚNICO por dispositivo (prefijo "P") que jamás colisiona con otro
// ni con la serie central; el panel lo recibe igual y queda trazable.
function localFallbackReservaId() {
  const t = Date.now().toString(36).toUpperCase().slice(-5);
  const r = Math.random().toString(36).toUpperCase().slice(2, 5);
  return 'RV-2026-P' + t + r;
}

// Folio correlativo CENTRAL y atómico (async). Resuelve a { id, source }.
//   source: 'server' = número correlativo real · 'local' = provisional offline.
function nextReservaIdAsync() {
  return fetch('api/reserva-id.php?t=' + Date.now(), { cache: 'no-store' })
    .then((r) => { if (!r.ok) throw new Error('http ' + r.status); return r.json(); })
    .then((j) => {
      if (j && j.ok && j.id) {
        // Mantener el contador local alineado (referencia/diagnóstico).
        if (j.seq) storeSetKey('reservaSeq', j.seq + 1);
        return { id: j.id, source: 'server' };
      }
      throw new Error('respuesta-invalida');
    })
    .catch(() => ({ id: localFallbackReservaId(), source: 'local' }));
}

// Folio síncrono SOLO de respaldo (no garantiza correlatividad entre dispositivos).
// Se conserva por compatibilidad; el flujo real usa nextReservaIdAsync().
function nextReservaId() {
  const s = storeGet();
  const seq = (s.reservaSeq && s.reservaSeq > 2099) ? s.reservaSeq : 2103;
  storeSetKey('reservaSeq', seq + 1);
  return 'RV-2026-' + seq;
}

// ---------- Store con persistencia (localStorage) ----------
const STORE_KEY = 'rivamar_v24';

function clone(x) { return JSON.parse(JSON.stringify(x)); }

function mergeDefaults(saved) {
  const base = clone(buildDefaults());
  const out = { ...base, ...(saved || {}) };
  ['site', 'nosotros', 'convenios', 'exponor'].forEach((k) => {
    if (saved && saved[k] && typeof saved[k] === 'object' && !Array.isArray(saved[k])) {
      out[k] = { ...base[k], ...saved[k] };
    }
  });
  return out;
}

function hydrate() {
  try {
    const saved = JSON.parse(localStorage.getItem(STORE_KEY) || '{}');
    return mergeDefaults(saved);
  } catch (e) { return clone(buildDefaults()); }
}

let STATE = hydrate();
const listeners = new Set();

function syncGlobals() {
  window.LOCALES = STATE.locales;
  window.LOCAL_MAP = Object.fromEntries(STATE.locales.map((l) => [l.id, l]));
  window.SLUG_MAP = Object.fromEntries(STATE.locales.map((l) => [l.slug, l]));
  window.GALERIA = STATE.galeria;
  window.STATS = STATE.stats;
  window.SITE = STATE.site;
  // Aplicar tema (paleta) al documento
  try {
    const root = document.documentElement;
    root.setAttribute('data-theme', (STATE.site && STATE.site.theme) || 'midnight');
    const blur = STATE.site && STATE.site.hero_blur != null ? STATE.site.hero_blur : 1.5;
    const ov = STATE.site && STATE.site.hero_overlay != null ? STATE.site.hero_overlay : 60;
    root.style.setProperty('--hero-blur', blur + 'px');
    root.style.setProperty('--hero-overlay', (ov / 100));
    // Locales (global)
    const lb = STATE.site && STATE.site.local_blur != null ? STATE.site.local_blur : 1.5;
    const lo = STATE.site && STATE.site.local_overlay != null ? STATE.site.local_overlay : 55;
    root.style.setProperty('--local-blur', lb + 'px');
    root.style.setProperty('--local-overlay', (lo / 100));
    // Nosotros
    const nb = STATE.nosotros && STATE.nosotros.blur != null ? STATE.nosotros.blur : 1.5;
    const no = STATE.nosotros && STATE.nosotros.overlay != null ? STATE.nosotros.overlay : 70;
    root.style.setProperty('--nos-blur', nb + 'px');
    root.style.setProperty('--nos-overlay', (no / 100));
    // EXPONOR
    const eb = STATE.exponor && STATE.exponor.blur != null ? STATE.exponor.blur : 1.5;
    const eo = STATE.exponor && STATE.exponor.overlay != null ? STATE.exponor.overlay : 75;
    root.style.setProperty('--exponor-blur', eb + 'px');
    root.style.setProperty('--exponor-overlay', (eo / 100));
  } catch (e) {}
}

function persist() { try { localStorage.setItem(STORE_KEY, JSON.stringify(STATE)); } catch (e) {} }
function emit() { listeners.forEach((fn) => fn()); }

function storeGet() { return STATE; }
function storeSet(patch) {
  STATE = { ...STATE, ...(typeof patch === 'function' ? patch(STATE) : patch) };
  syncGlobals(); persist(); pendingChanges = true; emit();
}
function storeSetKey(key, value) {
  storeSet((s) => ({ [key]: typeof value === 'function' ? value(s[key]) : value }));
}
function storeReset() { STATE = clone(buildDefaults()); syncGlobals(); persist(); emit(); }
function storeSubscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); }
function useStore() { return useSyncExternalStore(storeSubscribe, storeGet); }

syncGlobals(); // hidratar window.* antes de que rendericen los demás scripts

// ---------- Sincronización con el servidor (PHP + JSON en Hostinger) ----------
// Permite que TODOS los dispositivos lean la misma versión publicada.
const API_URL = 'api/data.php';
const PUBLISH_KEY = 'rivamar2026'; // misma clave que en api/data.php
let serverStatus = 'local';        // local | synced | empty | error
let pendingChanges = false;        // hay ediciones locales sin publicar
function getServerStatus() { return serverStatus; }
function hasPendingChanges() { return pendingChanges; }

function loadFromServer() {
  return fetch(API_URL + '?t=' + Date.now(), { cache: 'no-store' })
    .then((res) => { if (!res.ok) throw new Error('http'); return res.json(); })
    .then((data) => {
      if (data && data.site && data.locales) {
        STATE = mergeDefaults(data);
        syncGlobals(); persist();
        serverStatus = 'synced'; pendingChanges = false;
      } else { serverStatus = 'empty'; }
      emit();
    })
    .catch(() => { serverStatus = 'error'; emit(); });
}

function publishToServer() {
  return fetch(API_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ clave: PUBLISH_KEY, payload: STATE }),
  })
    .then((res) => res.json().then((j) => ({ res, j })).catch(() => ({ res, j: {} })))
    .then(({ res, j }) => {
      if (res.ok && j && j.ok) { serverStatus = 'synced'; pendingChanges = false; emit(); return { ok: true }; }
      return { ok: false, error: (j && j.error) || ('HTTP ' + res.status) };
    })
    .catch(() => ({ ok: false, error: 'sin-conexion' }));
}

// Marca cambios pendientes en cada edición del store
function markPending() { pendingChanges = true; }

// ---------- Bandeja de entrada: solicitudes desde cualquier dispositivo ----------
const INBOX_URL = 'api/inbox.php';
// Envía una reserva/cotización al servidor (cualquier dispositivo). Fire-and-forget.
function pushToInbox(tipo, item) {
  try {
    return fetch(INBOX_URL, {
      method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ tipo, item }),
    })
      .then((r) => r.json().then((j) => ({ status: r.status, j })).catch(() => ({ status: r.status, j: {} })))
      .then(({ status, j }) => {
        // 'dup' cuenta como entregada: ya estaba en el servidor.
        const ok = status >= 200 && status < 300 && j && (j.ok || j.dup);
        return { ok: !!ok, status, error: j && j.error };
      })
      .catch(() => ({ ok: false, error: 'sin-conexion' }));
  } catch (e) { return Promise.resolve({ ok: false, error: 'excepcion' }); }
}
// El panel admin lee la bandeja y agrega las solicitudes nuevas (por id) al store.
function loadInbox() {
  return fetch(INBOX_URL + '?t=' + Date.now(), { cache: 'no-store' })
    .then((r) => r.json())
    .then((d) => {
      if (!d) return { nuevas: 0 };
      let nuevas = 0;
      const idsR = new Set((STATE.reservas || []).map((x) => x.id));
      const nuevasR = (d.reservas || []).filter((x) => x && x.id && !idsR.has(x.id));
      const idsC = new Set((STATE.cotizaciones || []).map((x) => x.id));
      const nuevasC = (d.cotizaciones || []).filter((x) => x && x.id && !idsC.has(x.id));
      nuevas = nuevasR.length + nuevasC.length;
      if (nuevas > 0) {
        STATE = {
          ...STATE,
          reservas: [...nuevasR.reverse(), ...(STATE.reservas || [])],
          cotizaciones: [...nuevasC.reverse(), ...(STATE.cotizaciones || [])],
        };
        syncGlobals(); persist(); emit();
      }
      return { nuevas };
    })
    .catch(() => ({ nuevas: 0, error: true }));
}

// Intentar cargar la versión del servidor al iniciar (si no hay PHP, queda en localStorage)
try { loadFromServer(); } catch (e) {}

// ---------- Registro de visitas (clave separada, persiste entre versiones) ----------
const VISITS_KEY = 'rivamar_visits';
function getVisits() { try { return JSON.parse(localStorage.getItem(VISITS_KEY) || '[]'); } catch (e) { return []; } }
function saveVisits(arr) { try { localStorage.setItem(VISITS_KEY, JSON.stringify(arr.slice(-3000))); } catch (e) {} }
function clearVisits() { try { localStorage.removeItem(VISITS_KEY); } catch (e) {} }

function seedVisitsIfEmpty() {
  if (getVisits().length) return;
  const sampleIps = ['190.95.112.40', '200.27.88.15', '152.172.44.9', '190.44.120.77', '181.42.200.13', '200.83.55.201', '190.95.112.40', '152.172.44.9'];
  const uas = [
    'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 Mobile Safari',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Version/17 Safari',
    'Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 Chrome/124 Mobile Safari',
  ];
  const now = Date.now();
  const arr = [];
  for (let i = 0; i < 34; i++) {
    const daysAgo = Math.floor(Math.random() * 7);
    const ts = new Date(now - daysAgo * 86400000 - Math.floor(Math.random() * 80000000));
    arr.push({
      id: 's' + i, ts: ts.toISOString(),
      ip: sampleIps[Math.floor(Math.random() * sampleIps.length)],
      ua: uas[Math.floor(Math.random() * uas.length)],
      ref: ['', 'https://www.google.com/', 'https://exponor.cl/', 'https://instagram.com/'][Math.floor(Math.random() * 4)],
    });
  }
  arr.sort((a, b) => new Date(a.ts) - new Date(b.ts));
  saveVisits(arr);
}

// ---------- Envío automático de correo de reserva ----------
// Modo 1 (recomendado, SIN límites): PHP nativo en Hostinger (api/reserva-mail.php).
// Modo 2 (respaldo): EmailJS. Se intenta PHP primero; si no está, cae a EmailJS.
// ---------- Aviso al teléfono del admin (CallMeBot — WhatsApp gratis, sin límites) ----------
// El admin registra su teléfono una vez en callmebot.com y pega su apikey en el CMS.
function avisarTelefono(data) {
  const site = (window.SITE) || {};
  if (!site.notify_wa || !site.callmebot_phone || !site.callmebot_apikey) return Promise.resolve({ ok: false, reason: 'no-config' });
  const localNom = (window.LOCAL_MAP && window.LOCAL_MAP[data.local]) ? window.LOCAL_MAP[data.local].nombre : data.local;
  const txt = `RIVAMAR — Nueva reserva ${data.id}: ${data.nombre}, ${localNom}, ${data.fecha} ${data.hora}, ${data.pax} pax. Tel: ${data.telefono}`;
  const url = 'https://api.callmebot.com/whatsapp.php?phone=' + encodeURIComponent(site.callmebot_phone) +
    '&text=' + encodeURIComponent(txt) + '&apikey=' + encodeURIComponent(site.callmebot_apikey);
  try {
    // beacon por <img> evita problemas de CORS
    const img = new Image(); img.src = url;
    return Promise.resolve({ ok: true });
  } catch (e) { return Promise.resolve({ ok: false }); }
}

function enviarCorreoReserva(data) {
  const site = (window.SITE) || {};
  const localNom = (window.LOCAL_MAP && window.LOCAL_MAP[data.local]) ? window.LOCAL_MAP[data.local].nombre : data.local;
  const payload = {
    reserva_id: data.id, nombre: data.nombre, empresa: data.empresa || 'Particular',
    correo: data.correo, telefono: data.telefono, local: localNom,
    fecha: data.fecha, hora: data.hora, personas: data.pax,
    exponor: data.exponor ? 'Sí — 15%' : 'No', comentarios: data.comentarios || '—',
    email_destino: site.email_destino || site.contacto_correo || '',
  };
  if (!site.email_auto) return Promise.resolve({ ok: false, reason: 'desactivado' });

  // Modo PHP nativo (sin límites)
  if (site.email_modo !== 'emailjs') {
    return fetch('api/reserva-mail.php', {
      method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload),
    }).then((r) => r.json()).then((j) => {
      if (j && j.ok) return { ok: true, via: 'php' };
      return enviarPorEmailJS(site, payload);
    }).catch(() => enviarPorEmailJS(site, payload));
  }
  return enviarPorEmailJS(site, payload);
}

function enviarPorEmailJS(site, params) {
  if (!window.emailjs || !site.emailjs_public || !site.emailjs_service || !site.emailjs_template) {
    return Promise.resolve({ ok: false, reason: 'no-config' });
  }
  try {
    emailjs.init({ publicKey: site.emailjs_public });
    return emailjs.send(site.emailjs_service, site.emailjs_template, params)
      .then(() => ({ ok: true, via: 'emailjs' }))
      .catch((e) => ({ ok: false, reason: String(e && e.text || e) }));
  } catch (e) {
    return Promise.resolve({ ok: false, reason: String(e) });
  }
}

let __visitTracked = false;
function trackVisit() {
  if (__visitTracked) return; __visitTracked = true;
  seedVisitsIfEmpty();
  const visit = { id: String(Date.now()) + '-' + Math.random().toString(36).slice(2, 7), ts: new Date().toISOString(), ip: null, ua: navigator.userAgent, ref: document.referrer || '' };
  const arr = getVisits(); arr.push(visit); saveVisits(arr);
  // Intentar obtener IP pública (funciona en el sitio publicado; puede no estar disponible en vista previa local)
  try {
    fetch('https://api.ipify.org?format=json').then((r) => r.json()).then((d) => {
      const a = getVisits(); const idx = a.findIndex((v) => v.id === visit.id);
      if (idx >= 0) { a[idx].ip = d.ip; saveVisits(a); }
    }).catch(() => {});
  } catch (e) {}
}

Object.assign(window, {
  CAPACIDAD, MINIMO, HORARIOS, EXPONOR_CODE, EXPONOR_DCTO, EXPONOR_INICIO, CAT_LABEL,
  ROLES, ADMIN_MODULOS,
  buildDefaults, useStore, storeGet, storeSet, storeSetKey, storeReset, nextReservaId, nextReservaIdAsync,
  getVisits, clearVisits, trackVisit, enviarCorreoReserva, avisarTelefono,
  loadFromServer, publishToServer, getServerStatus, hasPendingChanges,
  pushToInbox, loadInbox,
  // compatibilidad con código existente:
  SEED_RESERVAS: STATE.reservas, SEED_USERS: STATE.users, GALERIA: STATE.galeria,
  CMS_DEFAULT: DEFAULT_SITE,
});
