/* data.jsx — Adaptador de datos REAL.
   Reemplaza el catálogo mock: ahora el menú viene de /api/products y
   /api/categories (los mismos del backend en producción). Mantiene la
   interfaz que esperan los componentes del diseño:
     window.PRODUCTS, window.CATEGORIES, window.SELLOS, window.cop
   y expone window.loadMenuData() (App la llama al montar). */

const SELLOS = {
  bestseller:  { label: 'Más Vendido',              fr: 'La favorite' },
  recommended: { label: 'Recomendado por la Casa',  fr: 'Recommandé par la maison' },
  healthy:     { label: 'Saludable',                fr: 'Léger & sain' },
  shareable:   { label: 'Para Compartir',           fr: 'À partager' },
  signature:   { label: 'Especialidad de la casa',  fr: 'Spécialité maison' },
  new:         { label: 'Novedad',                  fr: 'Nouveauté' },
};

const cop = (n) => '$' + Number(n || 0).toLocaleString('es-CO');

// Subtítulo editorial por categoría (conserva la elegancia del diseño)
const CAT_SUB = {
  brunch: 'De 8 a.m. a 12 m.', postres: 'Repostería fina',
  cheesecakes: 'Hechos en casa', entradas: 'Para empezar',
  pizzas: 'Masa madre', sandwiches: 'Pan de la casa',
  ensaladas: 'Frescas, del día', cocktails: 'Aperitivos & digestivos',
  calientes: 'Café de origen · Té', sin_alcohol: 'Frescas & naturales',
  malteadas: 'Heladas', otras: 'Carta complementaria',
};
const CAT_ORDER = ['brunch','postres','cheesecakes','entradas','pizzas','sandwiches','ensaladas','cocktails','calientes','sin_alcohol','malteadas','otras'];

// Origen de datos: si la página está DESPLEGADA (cualquier dominio real:
// alecastropasteleria.com, pasteleria.hitonetap.com, etc.) → mismo origen
// (relativo): cada servidor sirve su propia API/imágenes. Solo en review
// LOCAL (localhost) se apunta al espejo de producción (CORS abierto) para
// ver el catálogo/imágenes reales sin levantar datos locales.
const PROD_ORIGIN = 'https://pasteleria.hitonetap.com';
const _host = (typeof location !== 'undefined' && location.hostname) || '';
const IS_LOCAL = _host === 'localhost' || _host === '127.0.0.1' || _host === '0.0.0.0' || _host === '' || _host.slice(-6) === '.local';
const ON_PROD = !IS_LOCAL;                              // desplegado → mismo origen
const API_BASE = ON_PROD ? '' : PROD_ORIGIN;          // para fetch /api/*
const IMG_BASE = ON_PROD ? '' : PROD_ORIGIN;          // para /uploads/*
window.API_BASE = API_BASE;

function resolveImg(u) {
  if (!u) return '';
  if (/^https?:\/\//.test(u)) return u;                 // ya absoluta (queda igual)
  // u tipo "/uploads/NOMBRE.jpg"
  if (ON_PROD) return u.charAt(0) === '/' ? u : '/' + u; // prod: nativo, mismo origen
  const file = u.split('/').pop();                       // NOMBRE.jpg
  return '/_img/' + file;                                 // local: proxy → prod (sin hotlink)
}

// Globals que consumen los componentes (vacíos hasta cargar)
window.SELLOS = SELLOS;
window.cop = cop;
window.PRODUCTS = [];
window.CATEGORIES = [];

function adaptProduct(p) {
  const sellos = [];
  if (p.is_best_seller)  sellos.push('bestseller');
  if (p.is_recommended)  sellos.push('recommended');
  if (p.is_new)          sellos.push('new');
  if (p.is_for_sharing)  sellos.push('shareable');
  if (p.is_healthy)      sellos.push('healthy');

  const tags = [];
  if (p.is_vegan)        tags.push('veg');
  if (p.is_gluten_free)  tags.push('gf');

  let variants = [];
  try {
    if (p.variants) {
      const v = typeof p.variants === 'string' ? JSON.parse(p.variants) : p.variants;
      if (Array.isArray(v)) {
        variants = v
          .filter(x => x && (x.label || x.name))
          .map((x, i) => ({
            id: String(x.id || x.label || ('v' + i)),
            label: x.label || x.name || ('Opción ' + (i + 1)),
            price: Number(x.price) || Number(p.price) || 0,
          }));
      }
    }
  } catch (e) { /* variants malformed → none */ }

  // Si el nombre encierra opciones tipo "Margarita (Clásica/Frutos/Lulo/
  // Maracuyá)" y NO hay variantes reales del backend → nombre limpio +
  // variantes; el cliente escoge el sabor al pulsar "Añadir". (Pedido del
  // negocio: no meter los sabores en el nombre.)
  let cleanName = p.title || p.name || '';
  if (variants.length === 0) {
    const m = cleanName.match(/^(.+?)\s*\(([^)]+)\)\s*$/);
    if (m) {
      const opts = m[2]
        .split(/\s*[\/,·|]\s*|\s+o\s+/i)
        .map(x => x.trim())
        .filter(Boolean);
      if (opts.length >= 2 && m[1].trim().length >= 2) {
        cleanName = m[1].trim();
        variants = opts.map((label, i) => ({
          id: 'f' + i,
          label: label.charAt(0).toUpperCase() + label.slice(1),
          price: Number(p.price) || 0,
        }));
      }
    }
  }

  return {
    id: String(p.id),
    cat: p.category || 'otras',
    name: cleanName,
    desc: p.description || p.long_description || '',
    price: Number(p.price) || 0,
    sellos,
    tags,
    img: resolveImg(p.image_url),    // imagen REAL de producción (/uploads/…)
    soldOut: !!p.sold_out || p.stock_quantity === 0,
    hasMods: !!p.has_modifiers,
    variants,
    mods: [],                        // se cargan perezosamente en el detalle
  };
}

// App llama esto al montar; llena los globals desde la API real.
window.loadMenuData = async function loadMenuData() {
  const [pr, cr] = await Promise.all([
    fetch(API_BASE + '/api/products').then(r => r.ok ? r.json() : []).catch(() => []),
    fetch(API_BASE + '/api/categories').then(r => r.ok ? r.json() : []).catch(() => []),
  ]);

  const prods = (Array.isArray(pr) ? pr : [])
    .filter(p => p && p.active !== 0)
    .map(adaptProduct);
  window.PRODUCTS = prods;

  const present = new Set(prods.map(p => p.cat));
  let cats = (Array.isArray(cr) ? cr : [])
    .map(c => ({ id: c.key || c.id, label: c.label || c.key, sub: CAT_SUB[c.key || c.id] || '' }))
    .filter(c => c.id && present.has(c.id));

  // Respaldo: si /api/categories no trae nada, derivar de los productos
  if (cats.length === 0) {
    cats = [...present].map(id => ({ id, label: id.charAt(0).toUpperCase() + id.slice(1), sub: CAT_SUB[id] || '' }));
  }
  cats.sort((a, b) => ((CAT_ORDER.indexOf(a.id) + 1) || 99) - ((CAT_ORDER.indexOf(b.id) + 1) || 99));
  window.CATEGORIES = cats;

  // Asigna imágenes distintas y de mejor resolución a la landing
  // antes de que la app marque "listo" (evita parpadeo de fallback).
  try { await window.buildShowcase(); } catch (e) { window.SHOWCASE = window.SHOWCASE || {}; }

  return prods.length;
};

// Carga perezosa de modificadores para el detalle de un producto
window.loadProductMods = async function loadProductMods(productId) {
  try {
    const r = await fetch(API_BASE + '/api/products/' + encodeURIComponent(productId) + '/modifiers');
    if (!r.ok) return [];
    const groups = await r.json();
    const arr = Array.isArray(groups) ? groups : Object.values(groups || {});
    const mods = [];
    for (const g of arr) {
      for (const m of (g.modifiers || g.options || [])) {
        mods.push({
          id: String(m.id || m.mod_id || m._id),
          label: (g.title ? g.title + ': ' : '') + (m.title || m.mod_title || m.name || ''),
          price: Number(m.price_extra || m.price || 0),
        });
      }
    }
    return mods;
  } catch (e) { return []; }
};

// ─── Showcase del landing: imágenes REALES, DISTINTAS y de mejor
//     resolución. La carta de presentación no debe repetir fotos.
//     (Antes todo caía a images/hero.jpg porque las rutas reales son
//      relativas /_img|/uploads y el viejo filtro exigía https://.)

// ¿Es una ruta de imagen real usable? (absoluta o /uploads|/_img …)
function _looksImg(u) {
  return typeof u === 'string' && u.length > 0 &&
    (/^https?:\/\//.test(u) || u.charAt(0) === '/') &&
    /\.(jpe?g|png|webp|avif)(\?|#|$)/i.test(u);
}
window.hasImg = _looksImg;

// Mide la resolución natural de una imagen (con timeout).
function _measure(url) {
  return new Promise((resolve) => {
    let settled = false;
    const done = (w, h) => { if (!settled) { settled = true; resolve({ url, w, h, area: w * h }); } };
    try {
      const im = new Image();
      const t = setTimeout(() => done(0, 0), 6000);
      im.onload = () => { clearTimeout(t); done(im.naturalWidth || 0, im.naturalHeight || 0); };
      im.onerror = () => { clearTimeout(t); done(0, 0); };
      im.src = url;
    } catch (e) { done(0, 0); }
  });
}

// Mide un conjunto de URLs (concurrencia 6, caché por sesión).
async function _rankPool(urls) {
  let cache = {};
  try { cache = JSON.parse(sessionStorage.getItem('ac_imgres') || '{}'); } catch (e) {}
  const need = urls.filter(u => !cache[u]);
  let i = 0;
  const worker = async () => {
    while (i < need.length) { const u = need[i++]; const r = await _measure(u); cache[u] = [r.w, r.h]; }
  };
  await Promise.all(Array.from({ length: Math.min(6, need.length || 1) }, worker));
  try { sessionStorage.setItem('ac_imgres', JSON.stringify(cache)); } catch (e) {}
  const map = {};
  urls.forEach(u => { const c = cache[u] || [0, 0]; map[u] = { w: c[0], h: c[1], area: c[0] * c[1] }; });
  return map;
}

// Asigna, UNA sola vez al cargar, imágenes distintas y de mayor
// resolución a cada zona de la landing. Lo espera el boot (loadMenuData).
window.SHOWCASE = null;
window.buildShowcase = async function buildShowcase() {
  const ps = (window.PRODUCTS || []).filter(p => p && _looksImg(p.img));
  if (!ps.length) { window.SHOWCASE = {}; return; }

  // Pool priorizado y único por URL (destacados + categorías vitrina + resto)
  const seen = new Set(); const pool = [];
  const push = (p) => { if (p && !seen.has(p.img)) { seen.add(p.img); pool.push(p); } };
  ps.filter(p => p.sellos && (p.sellos.includes('signature') || p.sellos.includes('bestseller') ||
    p.sellos.includes('recommended') || p.sellos.includes('new'))).forEach(push);
  ['postres', 'cheesecakes', 'brunch', 'entradas', 'pizzas', 'sandwiches', 'ensaladas']
    .forEach(c => ps.filter(p => p.cat === c).slice(0, 6).forEach(push));
  ps.forEach(push);
  const cand = pool.slice(0, 22);

  // Mide resolución (presupuesto global ~5s; lo que no alcance → área 0)
  let res = {};
  try {
    res = await Promise.race([
      _rankPool(cand.map(p => p.img)),
      new Promise(r => setTimeout(() => r({}), 5000)),
    ]) || {};
  } catch (e) { res = {}; }
  const area = (u) => (res[u] && res[u].area) || 0;

  const ord = cand.slice().sort((a, b) => area(b.img) - area(a.img));
  const used = new Set();
  const take = (pred) => {
    const p = ord.find(x => !used.has(x.img) && (!pred || pred(x)));
    if (p) { used.add(p.img); return p.img; }
    return null;
  };
  const sc = {};
  // Hero = la de mayor resolución (preferir horizontal y grande); reservada.
  sc.hero = take(x => { const r = res[x.img]; return r && r.w >= r.h && r.area >= 300 * 300; }) ||
            take(x => area(x.img) >= 300 * 300) || take();
  sc.postres     = take(x => x.cat === 'postres')     || take();
  sc.brunch      = take(x => x.cat === 'brunch')      || take();
  sc.cheesecakes = take(x => x.cat === 'cheesecakes') || take();
  sc.maison      = take(); // siguiente mejor, distinta de todas las anteriores
  sc._used = used;         // URLs ya usadas → featured las excluye
  window.SHOWCASE = sc;
};

// Devuelve la foto asignada (distinta y de buena resolución) para una
// zona de la landing: 'hero' | 'postres' | 'brunch' | 'cheesecakes' | 'maison'.
window.pickImage = function pickImage(slot) {
  const sc = window.SHOWCASE;
  if (sc && typeof sc[slot] === 'string' && sc[slot]) return sc[slot];
  // Respaldo si aún no se construyó: real de esa categoría, o cualquiera real.
  const ps = window.PRODUCTS || [];
  const cat = { postres: 'postres', brunch: 'brunch', cheesecakes: 'cheesecakes' }[slot];
  let p = cat && ps.find(x => x.cat === cat && _looksImg(x.img));
  if (!p) p = ps.find(x => _looksImg(x.img));
  return p ? p.img : 'images/hero.jpg';
};
