// Moderis — bewerkbare optie-preview.
// Bekijk een suggestie, pas 'm aan (ander ingrediënt of andere hoeveelheid),
// de macro's herberekenen. De preview start direct op de waarden die het
// recept al kent (per100 uit de jsonb — geen 0-flits), maar haalt meteen bij
// het openen ALLE macro's vers van de server: de pipeline (voorraad → basis →
// db → OFF → AI) is de waarheid en moet zo dicht mogelijk bij de realiteit
// staan. Een gewichtswijziging herschaalt daarna direct lokaal (geen call);
// een naamswijziging zoekt dat ene ingrediënt opnieuw op. "Dit eet ik" logt
// + haalt van de voorraad af. Bij een gewijzigde SAMENSTELLING vraagt de app
// of je het wilt bewaren.

function optieIngKey(ings) {
  return (ings || [])
    .map((i) => String(i.naam || '').trim().toLowerCase())
    .filter(Boolean).sort().join('|');
}

function OptieSheet({ meal, optieIdx, onClose, onEat, onChoose, showToast }) {
  const { useState, useRef, useEffect } = React;
  const optie = (meal.opties || [])[optieIdx] || {};
  const rnd = (n) => Math.round((Number(n) || 0) * 10) / 10;

  const [naam, setNaam] = useState(optie.name || '');
  // _orig = de oorspronkelijke hoeveelheid — anker voor de portie-schuif
  // (½×…1½×), zodat herhaald schuiven niet cumulatief afrondt.
  const [regels, setRegels] = useState(() => (optie.ingredienten || []).map((i) => {
    const g = i.hoeveelheid_g != null && i.hoeveelheid_g !== '' ? Number(i.hoeveelheid_g) : null;
    // Macro's die de caller al kent (per100 uit het recept, of afleidbaar uit
    // kcal + gram) meteen gebruiken — geen lookup en geen verspringende cijfers.
    let per100 = (i.per100 && i.per100.kcal_100g != null) ? i.per100 : null;
    if (!per100 && g > 0 && i.kcal != null) {
      const f = 100 / g;
      per100 = { kcal_100g: rnd((Number(i.kcal) || 0) * f), eiwitten_100g: rnd((Number(i.eiwitten) || 0) * f),
        koolhydraten_100g: rnd((Number(i.koolhydraten) || 0) * f), vetten_100g: rnd((Number(i.vetten) || 0) * f) };
    }
    const k = per100 && g != null ? g / 100 : 0;
    return {
      naam: i.naam || '', hoeveelheid_g: g != null ? g : '',
      _orig: g, per100,
      kcal: per100 ? rnd(per100.kcal_100g * k) : 0,
      eiwitten: per100 ? rnd(per100.eiwitten_100g * k) : 0,
      koolhydraten: per100 ? rnd(per100.koolhydraten_100g * k) : 0,
      vetten: per100 ? rnd(per100.vetten_100g * k) : 0,
      geschat: !!i.geschat,
    };
  }));
  const [busy, setBusy] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [factor, setFactor] = useState(1);
  const origKey = useRef(optieIngKey(optie.ingredienten));

  // Portie-schuif: alle (oorspronkelijke) hoeveelheden × f. Met per100 rekenen
  // we exact; anders schalen de macro's lineair mee. Handmatig toegevoegde
  // regels (zonder _orig) blijven staan zoals je ze invulde.
  const pasFactor = (f) => {
    setFactor(f);
    setRegels((prev) => prev.map((it) => {
      const orig = Number(it._orig) || 0;
      if (!orig) return it;
      const g = Math.round(orig * f);
      if (it.per100) {
        const k = g / 100;
        return { ...it, hoeveelheid_g: g,
          kcal: rnd(it.per100.kcal_100g * k), eiwitten: rnd(it.per100.eiwitten_100g * k),
          koolhydraten: rnd(it.per100.koolhydraten_100g * k), vetten: rnd(it.per100.vetten_100g * k) };
      }
      const cur = Number(it.hoeveelheid_g) || 0;
      if (cur > 0) {
        const s = g / cur;
        return { ...it, hoeveelheid_g: g,
          kcal: rnd(it.kcal * s), eiwitten: rnd(it.eiwitten * s),
          koolhydraten: rnd(it.koolhydraten * s), vetten: rnd(it.vetten * s) };
      }
      return { ...it, hoeveelheid_g: g };
    }));
  };

  // "Dit eet ik": meteen op slot (disabled + label) zodat een dubbele tik niet
  // twee keer logt en je direct ziet dat er iets gebeurt.
  const eet = async () => {
    if (busy || submitting) return;
    setSubmitting(true);
    try { await onEat(bouwPayload()); }
    finally { setSubmitting(false); }
  };

  // Totaal = som van de regels (client-side, geen call nodig).
  const macros = regels.reduce((s, r) => ({
    kcal: s.kcal + (Number(r.kcal) || 0),
    eiwitten: s.eiwitten + (Number(r.eiwitten) || 0),
    koolhydraten: s.koolhydraten + (Number(r.koolhydraten) || 0),
    vetten: s.vetten + (Number(r.vetten) || 0),
  }), { kcal: 0, eiwitten: 0, koolhydraten: 0, vetten: 0 });

  // Eénmalig bij openen: ALLE regels vers van de server berekenen — de
  // opgeslagen waarden zijn slechts de startweergave; de pipeline bepaalt de
  // werkelijkheid. Daarna alleen nog per gewijzigd ingrediënt.
  useEffect(() => { herberekenAlle(); /* eslint-disable-next-line */ }, []);

  const herberekenAlle = async () => {
    const idxs = regels.map((r, i) => ({ r, i })).filter((x) => String(x.r.naam).trim());
    if (!idxs.length) return;
    setBusy(true);
    try {
      const resp = await api.berekenMacros(idxs.map((x) => ({ naam: x.r.naam.trim(), hoeveelheid_g: Number(x.r.hoeveelheid_g) || 0 })));
      const verr = resp.ingredienten || [];
      setRegels((prev) => {
        const next = [...prev];
        idxs.forEach((x, k) => {
          const v = verr[k];
          if (!v || !next[x.i]) return;
          // Schaal naar de HUIDIGE grammen: pas je tijdens het berekenen al
          // iets aan, dan overschrijft de respons dat niet met oude waarden.
          const f = (Number(next[x.i].hoeveelheid_g) || 0) / 100;
          const p = v.per100;
          next[x.i] = { ...next[x.i], per100: p, geschat: v.geschat,
            kcal: p ? rnd(p.kcal_100g * f) : v.kcal,
            eiwitten: p ? rnd(p.eiwitten_100g * f) : v.eiwitten,
            koolhydraten: p ? rnd(p.koolhydraten_100g * f) : v.koolhydraten,
            vetten: p ? rnd(p.vetten_100g * f) : v.vetten };
        });
        return next;
      });
    } catch (err) { showToast('Herberekenen mislukt: ' + err.message); }
    setBusy(false);
  };

  // Alleen dit ene ingrediënt opnieuw opzoeken (na een naamswijziging).
  const herberekenEen = async (idx, rijNu) => {
    const r = rijNu || regels[idx];
    if (!String(r.naam).trim()) return;
    setBusy(true);
    try {
      const resp = await api.berekenMacros([{ naam: r.naam.trim(), hoeveelheid_g: Number(r.hoeveelheid_g) || 0 }]);
      const v = (resp.ingredienten || [])[0];
      if (v) setRegels((prev) => prev.map((it, i) => {
        if (i !== idx) return it;
        // Schaal naar de huidige grammen — die kunnen intussen gewijzigd zijn.
        const f = (Number(it.hoeveelheid_g) || 0) / 100;
        const p = v.per100;
        return { ...it, per100: p, geschat: v.geschat,
          kcal: p ? rnd(p.kcal_100g * f) : v.kcal,
          eiwitten: p ? rnd(p.eiwitten_100g * f) : v.eiwitten,
          koolhydraten: p ? rnd(p.koolhydraten_100g * f) : v.koolhydraten,
          vetten: p ? rnd(p.vetten_100g * f) : v.vetten };
      }));
    } catch (err) { showToast('Herberekenen mislukt: ' + err.message); }
    setBusy(false);
  };

  const setNaamRegel = (idx, v) => setRegels((prev) => prev.map((it, i) => i === idx ? { ...it, naam: v } : it));

  // Gewicht wijzigen → direct herschalen uit per100 (geen call).
  const setGram = (idx, val) => setRegels((prev) => prev.map((it, i) => {
    if (i !== idx) return it;
    const g = Number(val) || 0;
    if (it.per100) {
      const f = g / 100;
      return { ...it, hoeveelheid_g: val,
        kcal: rnd(it.per100.kcal_100g * f), eiwitten: rnd(it.per100.eiwitten_100g * f),
        koolhydraten: rnd(it.per100.koolhydraten_100g * f), vetten: rnd(it.per100.vetten_100g * f) };
    }
    return { ...it, hoeveelheid_g: val };
  }));

  const addIng = () => setRegels((prev) => [...prev, { naam: '', hoeveelheid_g: '', _orig: null, per100: null, kcal: 0, eiwitten: 0, koolhydraten: 0, vetten: 0, geschat: false }]);
  const removeIng = (idx) => setRegels((prev) => prev.filter((_, i) => i !== idx));

  const kiesIngredient = (idx, r) => {
    setRegels((prev) => prev.map((it, i) => i === idx ? { ...it, naam: r.naam } : it));
    herberekenEen(idx, { naam: r.naam, hoeveelheid_g: regels[idx].hoeveelheid_g });
  };

  const bouwPayload = () => {
    const lijst = regels
      .map((r) => ({ naam: String(r.naam || '').trim(), hoeveelheid_g: Number(r.hoeveelheid_g) || 0 }))
      .filter((i) => i.naam);
    return {
      naam: naam.trim() || optie.name,
      kcal: Math.round(macros.kcal), eiwitten: Math.round(macros.eiwitten),
      koolhydraten: Math.round(macros.koolhydraten), vetten: Math.round(macros.vetten),
      ingredienten: lijst,
      receptId: optie.receptId || null,
      veranderd: optieIngKey(lijst) !== origKey.current,
    };
  };

  const inputStyle = {
    width: '100%', boxSizing: 'border-box', padding: '9px 11px', fontSize: 13.5,
    border: '1px solid var(--m-line-2)', borderRadius: 11, background: 'var(--m-card)', fontFamily: 'inherit',
  };

  return (
    <Sheet title={meal.moment} onClose={onClose}>
      <input value={naam} onChange={(e) => setNaam(e.target.value)}
        style={{ ...inputStyle, fontSize: 16, fontWeight: 700, padding: '10px 12px', marginBottom: 10 }} />

      <div style={{ display: 'flex', gap: 7, alignItems: 'center', flexWrap: 'wrap', marginBottom: 14 }}>
        <span className="num" style={{ fontSize: 16, fontWeight: 700 }}>{Math.round(macros.kcal)}</span>
        <span style={{ fontSize: 12, color: 'var(--ink-3)', marginRight: 2 }}>kcal</span>
        <MacroBadges m={{ p: Math.round(macros.eiwitten), c: Math.round(macros.koolhydraten), f: Math.round(macros.vetten) }} size={12} />
        {optie.soortMeta && <span className={`m-badge ${optie.soortMeta.cls}`}>{optie.soortMeta.tag}</span>}
        <InHuisBadge m={optie} size={10.5} />
        {busy && <span style={{ fontSize: 11, color: 'var(--ink-3)', display: 'inline-flex', alignItems: 'center', gap: 5 }}><Spinner size={11} /> berekenen…</span>}
      </div>

      {/* Portie-schuif — hetzelfde gerecht, kleinere of grotere portie */}
      {regels.some((r) => Number(r._orig) > 0) && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 14, flexWrap: 'wrap' }}>
          <span className="m-eyebrow" style={{ marginRight: 4 }}>Portie</span>
          {/* disabled zolang de eerste berekening loopt — anders schaal je
              waarden die de respons zo overschrijft */}
          {[[0.5, '½×'], [0.75, '¾×'], [1, '1×'], [1.25, '1¼×'], [1.5, '1½×']].map(([f, lbl]) => (
            <button key={f} className={'m-chip' + (factor === f ? ' is-active' : '')}
              onClick={() => pasFactor(f)} disabled={busy}
              style={{ padding: '6px 12px', fontSize: 12, ...(busy ? { opacity: 0.5, cursor: 'wait' } : {}) }}>
              {lbl}
            </button>
          ))}
        </div>
      )}

      <label className="m-eyebrow" style={{ display: 'block', marginBottom: 8 }}>Ingrediënten (pas gerust aan)</label>
      {optie.portieNote && (
        <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 8 }}>{optie.portieNote}</div>
      )}
      <div style={{ marginBottom: 8 }}>
        {regels.map((ing, idx) => (
          <div key={idx} style={{ display: 'flex', gap: 7, alignItems: 'center', marginBottom: 7 }}>
            <IngredientNaamInput value={ing.naam}
              onChange={(v) => setNaamRegel(idx, v)}
              onPick={(r) => kiesIngredient(idx, r)}
              onBlur={() => herberekenEen(idx)}
              style={{ ...inputStyle, flex: 1 }} />
            <input type="number" min="0" value={ing.hoeveelheid_g} onChange={(e) => setGram(idx, e.target.value)} placeholder="g"
              style={{ ...inputStyle, width: 64 }} />
            <span style={{ width: 40, flex: '0 0 auto', textAlign: 'right', fontSize: 11, color: 'var(--ink-3)' }} className="num">{Math.round(ing.kcal || 0)}</span>
            <span style={{ width: 12, flex: '0 0 auto', textAlign: 'center', color: 'var(--macro-fat)', fontSize: 12 }}>{ing.geschat ? '⚠' : ''}</span>
            <button className="tap" onClick={() => removeIng(idx)} title="Verwijder"
              style={{ width: 28, height: 28, flex: '0 0 auto', padding: 0, borderRadius: 8, border: '1px solid var(--m-line)',
                background: 'var(--m-card)', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <MIcon name="minus" size={13} color="var(--ink-2)" />
            </button>
          </div>
        ))}
      </div>
      <button className="tap" onClick={addIng}
        style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: 'none', border: 'none',
          color: 'var(--forest-600)', fontSize: 12.5, fontWeight: 600, cursor: 'pointer', padding: '2px 0', marginBottom: 16 }}>
        <MIcon name="plus" size={14} color="var(--forest-600)" /> Ingrediënt toevoegen
      </button>

      {optie.bereiding && (
        <div style={{ marginBottom: 16 }}>
          <div className="m-eyebrow" style={{ marginBottom: 6 }}>Bereiding</div>
          <div style={{ fontSize: 12.5, lineHeight: 1.55, color: 'var(--forest-950)', whiteSpace: 'pre-wrap' }}>{optie.bereiding}</div>
        </div>
      )}

      <button className="m-btn m-btn-primary tap" onClick={eet} disabled={busy || submitting}
        style={{ width: '100%', fontSize: 14.5, padding: '13px', opacity: (busy || submitting) ? 0.6 : 1 }}>
        {submitting ? <Spinner size={16} /> : <MIcon name="check" size={16} sw={2.2} color="var(--on-forest)" />} {submitting ? 'Loggen…' : 'Dit eet ik'}
      </button>
      {/* Alleen tonen als de caller een kies-zonder-eten-actie heeft (legacy) */}
      {onChoose && (
        <button className="m-btn m-btn-ghost tap" onClick={() => onChoose(optieIdx)} disabled={submitting}
          style={{ width: '100%', fontSize: 13, padding: '10px', marginTop: 8 }}>
          Alleen kiezen (nog niet eten)
        </button>
      )}
    </Sheet>
  );
}

Object.assign(window, { OptieSheet });
