﻿/* ComboConfig modal.
   Lets the user pick which items fill each slot (e.g. 15 recipientes, 15 filetes)
   and never allows more than the combo includes. */

function ItemPicker({ item, qty, canAdd, onInc, onDec }) {
  return (
    <div className={'cfg-item' + (qty > 0 ? ' on' : '')}>
      <div className="cfg-thumb" style={{ background: item.img ? 'var(--eo-white)' : `color-mix(in srgb, ${item.color} 18%, white)` }}>
        {item.img ? <img src={item.img} alt="" /> : <span className="cfg-dot" style={{ background: item.color }}></span>}
      </div>
      <div className="cfg-item-info">
        <div className="cfg-item-name">{item.name}</div>
        {item.unit && <div className="cfg-item-unit">{item.unit}</div>}
      </div>
      {qty > 0 ? (
        <div className="stepper sm">
          <button onClick={onDec} aria-label="Quitar"><Icon name={qty === 1 ? 'Trash' : 'Minus'} size={qty === 1 ? 13 : 14}/></button>
          <span>{qty}</span>
          <button onClick={onInc} disabled={!canAdd} aria-label="Agregar"><Icon name="Plus" size={14}/></button>
        </div>
      ) : (
        <button className="cfg-add" onClick={onInc} disabled={!canAdd} aria-label="Agregar"><Icon name="Plus" size={18}/></button>
      )}
    </div>
  );
}

function ComboSlot({ slot, sel, onInc, onDec, onFill, atLimit }) {
  const pool = slot.poolItems || window.EO_DATA.comboPool(slot.pool);
  const total = Object.values(sel).reduce((s, n) => s + n, 0);
  const full = total >= slot.qty;
  const pct = Math.min(100, Math.round((total / slot.qty) * 100));

  // group pool items by their `group` label
  const groups = {};
  pool.forEach((it) => { (groups[it.group] = groups[it.group] || []).push(it); });
  const groupNames = Object.keys(groups);

  return (
    <section className="cfg-slot">
      <div className="cfg-slot-head">
        <div>
          <h4 className="cfg-slot-title">{slot.label}</h4>
          {slot.sub && <p className="cfg-slot-sub">{slot.sub}</p>}
        </div>
        <div className={'cfg-count' + (full ? ' full' : '')}>
          {full ? <Icon name="Check" size={16}/> : null}
          <span><b>{total}</b> / {slot.qty}</span>
        </div>
      </div>

      <div className="cfg-bar"><span className={'cfg-bar-fill' + (full ? ' full' : '')} style={{ width: pct + '%' }}></span></div>

      <div className="cfg-slot-tools">
        <span className="cfg-help">
          {full ? '¡Cupo completo!' : `Elige ${slot.qty - total} ${slot.unit} más`}
        </span>
        <button className="cfg-fill" onClick={() => onFill(slot)} disabled={full}>
          <Icon name="Sparkles" size={14}/> Autocompletar
        </button>
      </div>

      {groupNames.map((g) => (
        <React.Fragment key={g}>
          {groupNames.length > 1 && <div className="cfg-group-label">{g}</div>}
          <div className="cfg-grid">
            {groups[g].map((it) => (
              <ItemPicker
                key={it.id} item={it}
                qty={sel[it.id] || 0}
                canAdd={!full && !(atLimit && atLimit(it.id))}
                onInc={() => onInc(slot, it.id)}
                onDec={() => onDec(slot, it.id)}
              />
            ))}
          </div>
        </React.Fragment>
      ))}
    </section>
  );
}

const ADOBOS = ['Sin adobo', 'Adobo verde', 'Adobo pimentón'];

function ComboConfig({ combo, initial, initialAdobo, initialSwaps, slots, includes, despensa, onClose, onConfirm }) {
  const BASE_SLOTS = slots || combo.slots || [];
  const INCLUDES = includes || combo.includes || [];
  // Límites por ítem: se combinan los de todos los slots (ids únicos).
  const LIMITS = Object.assign({}, ...BASE_SLOTS.map((s) => s.itemLimits || {}));
  // Adobo único para todo el combo (combos surtidos de proteína).
  const adoboNeeded = BASE_SLOTS.some((s) => s.adobo);
  const [adobo, setAdobo] = React.useState(initialAdobo || 'Adobo verde');

  // Mecánica de despensa: quitar ítems suma cupos a filetes/recipientes.
  const [swaps, setSwaps] = React.useState(initialSwaps || []);
  const swapCountFor = (slotId) => swaps.filter((s) => s.target === slotId).length;
  const effQty = (s) => s.qty + (despensa ? swapCountFor(s.id) * despensa.blockSize : 0);
  // SLOTS con el cupo efectivo (base + cambios).
  const SLOTS = BASE_SLOTS.map((s) => ({ ...s, qty: effQty(s) }));

  const addSwap = (item, target) => setSwaps((prev) => {
    if (prev.some((s) => s.item === item)) return prev;
    if (prev.length >= despensa.maxSwaps) return prev;
    return [...prev, { item, target }];
  });
  const removeSwap = (item) => setSwaps((prev) => prev.filter((s) => s.item !== item));
  const setSwapTarget = (item, target) => setSwaps((prev) => prev.map((s) => s.item === item ? { ...s, target } : s));
  const [sel, setSel] = React.useState(() => {
    const base = {};
    SLOTS.forEach((s) => { base[s.id] = (initial && initial[s.id]) ? { ...initial[s.id] } : {}; });
    return base;
  });

  const slotTotal = (id) => Object.values(sel[id] || {}).reduce((s, n) => s + n, 0);

  // Mapa id de ítem → clave de límite. Varias opciones de adobo de una misma
  // proteína comparten limitKey (el id del producto), así el límite aplica sobre
  // la suma de sus adobos.
  const idToKey = {};
  SLOTS.forEach((s) => (s.poolItems || []).forEach((it) => { idToKey[it.id] = it.limitKey || it.id; }));
  const keyOf = (itemId) => idToKey[itemId] || itemId;

  // Total en TODO el combo de todos los ítems que comparten una clave de límite.
  const keyTotalIn = (state, key) =>
    Object.values(state).reduce((sum, slotSel) =>
      sum + Object.entries(slotSel).reduce((s, [iid, q]) => s + (keyOf(iid) === key ? q : 0), 0), 0);

  // ¿El producto (o grupo de adobos) llegó a su límite?
  const atLimit = (itemId) => {
    const key = keyOf(itemId);
    const max = LIMITS[key];
    return max != null && keyTotalIn(sel, key) >= max;
  };

  const inc = (slot, itemId) => setSel((prev) => {
    if (slotTotal(slot.id) >= slot.qty) return prev;
    const key = keyOf(itemId);
    const max = LIMITS[key];
    if (max != null && keyTotalIn(prev, key) >= max) return prev;
    return { ...prev, [slot.id]: { ...prev[slot.id], [itemId]: (prev[slot.id][itemId] || 0) + 1 } };
  });
  const dec = (slot, itemId) => setSel((prev) => {
    const cur = (prev[slot.id][itemId] || 0) - 1;
    const slotSel = { ...prev[slot.id] };
    if (cur <= 0) delete slotSel[itemId]; else slotSel[itemId] = cur;
    return { ...prev, [slot.id]: slotSel };
  });
  const fill = (slot) => setSel((prev) => {
    const pool = slot.poolItems || window.EO_DATA.comboPool(slot.pool);
    const slotSel = { ...prev[slot.id] };
    let total = Object.values(slotSel).reduce((s, n) => s + n, 0);
    // Total por clave contando otros slots + lo que llevamos en este slot.
    const keyTotalFill = (key) => {
      let t = 0;
      for (const [sid, ss] of Object.entries(prev)) {
        if (sid === slot.id) continue;
        for (const [iid, q] of Object.entries(ss)) if (keyOf(iid) === key) t += q;
      }
      for (const [iid, q] of Object.entries(slotSel)) if (keyOf(iid) === key) t += q;
      return t;
    };
    const placeable = (it) => {
      const max = LIMITS[keyOf(it.id)];
      return max == null || keyTotalFill(keyOf(it.id)) < max;
    };
    // Reparte cíclicamente entre los ítems disponibles (respetando límites).
    let i = 0, guard = 0;
    while (total < slot.qty && pool.length && guard < 5000) {
      guard++;
      if (!pool.some(placeable)) break; // ninguno disponible → salir
      const it = pool[i % pool.length];
      i++;
      if (!placeable(it)) continue;
      slotSel[it.id] = (slotSel[it.id] || 0) + 1;
      total++;
    }
    return { ...prev, [slot.id]: slotSel };
  });

  const remaining = SLOTS.reduce((acc, s) => {
    const left = s.qty - slotTotal(s.id);
    if (left > 0) acc.push(`${left} ${s.unit}`);
    else if (left < 0) acc.push(`quita ${-left} ${s.unit}`);
    return acc;
  }, []);
  const complete = remaining.length === 0;

  return (
    <React.Fragment>
      <div className="cfg-scrim" onClick={onClose}></div>
      <div className="cfg-modal" role="dialog" aria-label={'Personalizar ' + combo.name}>
        <header className="cfg-head" style={{ background: combo.color }}>
          <div className="cfg-head-row">
            <div>
              <div className="cfg-eyebrow">Personaliza tu combo</div>
              <h3 className="cfg-title">{combo.name}</h3>
            </div>
            <button className="cfg-close" onClick={onClose} aria-label="Cerrar"><Icon name="X" size={20}/></button>
          </div>
          <div className="cfg-head-meta">
            <span className="cfg-price">{window.eoMoney(combo.price)}</span>
            <span className="cfg-dot-sep">·</span>
            <span className="cfg-incl"><Icon name="Truck" size={14}/> Domicilio incluido en Cali</span>
          </div>
        </header>

        <div className="cfg-body">
          <p className="cfg-intro">
            Tú eliges qué llevas. Marca los productos hasta completar cada cupo —
            <b> no puedes pasarte de lo que incluye el combo.</b>
          </p>

          {SLOTS.map((slot) => (
            <ComboSlot key={slot.id} slot={slot} sel={sel[slot.id]} onInc={inc} onDec={dec} onFill={fill} atLimit={atLimit} />
          ))}

          {adoboNeeded && (
            <section className="cfg-adobo">
              <div className="cfg-group-label">Adobo para los filetes</div>
              <div className="cfg-adobo-opts">
                {ADOBOS.map((a) => (
                  <button
                    key={a}
                    className={'cfg-adobo-opt' + (adobo === a ? ' on' : '')}
                    onClick={() => setAdobo(a)}
                  >
                    {adobo === a && <Icon name="Check" size={14} />} {a}
                  </button>
                ))}
              </div>
            </section>
          )}

          {despensa && (
            <section className="cfg-despensa">
              <div className="cfg-group-label">Despensa incluida</div>
              <p className="cfg-despensa-help">
                Puedes quitar hasta {despensa.maxSwaps}. Por cada uno que quites, suma&nbsp;
                {despensa.blockSize} filetes o {despensa.blockSize} recipientes.
              </p>
              <ul className="cfg-despensa-list">
                {despensa.items.map((it) => {
                  const sw = swaps.find((s) => s.item === it);
                  const canRemove = !!sw || swaps.length < despensa.maxSwaps;
                  return (
                    <li key={it} className={'cfg-despensa-item' + (sw ? ' removed' : '')}>
                      <span className="cfg-despensa-name"><Icon name="Check" size={14} /> {it}</span>
                      {!sw ? (
                        <button className="cfg-despensa-btn" disabled={!canRemove} onClick={() => addSwap(it, 'filetes')}>
                          <Icon name="X" size={13} /> Quitar
                        </button>
                      ) : (
                        <span className="cfg-despensa-swap">
                          <button className={'cfg-swap-opt' + (sw.target === 'filetes' ? ' on' : '')} onClick={() => setSwapTarget(it, 'filetes')}>+{despensa.blockSize} filetes</button>
                          <button className={'cfg-swap-opt' + (sw.target === 'recipientes' ? ' on' : '')} onClick={() => setSwapTarget(it, 'recipientes')}>+{despensa.blockSize} recip.</button>
                          <button className="cfg-despensa-undo" onClick={() => removeSwap(it)} title="Deshacer">↩</button>
                        </span>
                      )}
                    </li>
                  );
                })}
              </ul>
            </section>
          )}

          {INCLUDES.length > 0 && (
            <section className="cfg-includes">
              <div className="cfg-group-label">También incluye (ya va en tu combo)</div>
              <ul className="cfg-incl-list">
                {INCLUDES.map((it, i) => (
                  <li key={i}><Icon name="Check" size={15}/> {it}</li>
                ))}
              </ul>
            </section>
          )}
        </div>

        <footer className="cfg-foot">
          <span className={'cfg-status' + (complete ? ' ok' : '')}>
            {complete
              ? <React.Fragment><Icon name="Check" size={17}/> ¡Todo listo para agregar!</React.Fragment>
              : <React.Fragment>Te falta elegir: <b>{remaining.join(' · ')}</b></React.Fragment>}
          </span>
          <div className="cfg-foot-btns">
            <button className="btn btn-ghost" onClick={onClose}>Cancelar</button>
            <button className="btn btn-primary" disabled={!complete} onClick={() => onConfirm(sel, adobo, swaps)}>
              <Icon name="Check" size={18}/> {initial ? 'Guardar cambios' : 'Agregar al pedido'}
            </button>
          </div>
        </footer>
      </div>
    </React.Fragment>
  );
}

window.ComboConfig = ComboConfig;
