// recipes-sheet.jsx — meal-plan quick-add bottom sheet for Lista v2.
// Browse recipes, expand ingredients, "Add all" missing ones — plus create
// your own recipes and delete any (persisted to localStorage).
// Exposes window.RecipeSheet.
(function () {
const { useState, useEffect } = React;
const Ico = window.Ico;
const lc = (s) => s.trim().toLowerCase();

// ── persistence: custom recipes + removed built-ins ─────────────────
const R_KEY = 'lista:recipes:v1';
const loadStore = () => { try { return JSON.parse(localStorage.getItem(R_KEY)) || { custom: [], removed: [] }; } catch (e) { return { custom: [], removed: [] }; } };
const saveStore = (s) => { try { localStorage.setItem(R_KEY, JSON.stringify(s)); } catch (e) {} };
const allRecipes = (store) => [
  ...(window.RECIPES || []).filter((r) => !store.removed.includes(r.id)),
  ...store.custom,
];

const RECIPE_EMOJIS = ['\uD83C\uDF7D\uFE0F', '\uD83C\uDF2E', '\uD83C\uDF5D', '\uD83E\uDD58', '\uD83C\uDF72', '\uD83E\uDD57', '\uD83C\uDF55', '\uD83C\uDF63', '\uD83C\uDF54', '\uD83E\uDD5E', '\uD83C\uDF5C', '\uD83E\uDD69'];

function RecipeSheet({ t, locale, open, list, onAdd, onClose }) {
  const L = window.I18N_T ? window.I18N_T(locale || 'en') : null;
  const tr = (k) => (L ? L.ui(k) : k);
  const trItem = (n) => (L ? L.item(n) : n);
  const [store, setStore] = useState(loadStore);
  const [openId, setOpenId] = useState(null);
  const [addedId, setAddedId] = useState(null);
  const [editing, setEditing] = useState(false);
  const [editingId, setEditingId] = useState(null);
  const [name, setName] = useState('');
  const [emoji, setEmoji] = useState(RECIPE_EMOJIS[0]);
  const [ings, setIngs] = useState([]);
  const [ingQ, setIngQ] = useState('');
  useEffect(() => {
    if (open) { setStore(loadStore()); setOpenId(null); setAddedId(null); setEditing(false); }
  }, [open]);
  if (!open || !list) return null;

  const present = new Set(list.items.filter((i) => !i.checked).map((i) => lc(i.name)));
  const recipes = allRecipes(store);

  const update = (next) => { setStore(next); saveStore(next); };
  const deleteRecipe = (r) => {
    const isCustom = store.custom.some((c) => c.id === r.id);
    update(isCustom
      ? { ...store, custom: store.custom.filter((c) => c.id !== r.id) }
      : { ...store, removed: [...store.removed, r.id] });
    if (openId === r.id) setOpenId(null);
  };
  const addAll = (r, missing) => {
    if (!missing.length) return;
    onAdd(missing.map((m) => m.name));
    setAddedId(r.id);
    setTimeout(() => setAddedId(null), 1400);
  };
  const startNew = () => { setName(''); setEmoji(RECIPE_EMOJIS[0]); setIngs([]); setIngQ(''); setEditingId(null); setEditing(true); };
  const startEdit = (r) => {
    setName(trItem(r.name)); setEmoji(r.emoji || RECIPE_EMOJIS[0]);
    setIngs(r.ingredients.map((g) => g.name)); setIngQ(''); setEditingId(r.id); setEditing(true);
  };
  const addIng = () => {
    const v = ingQ.trim();
    if (!v || ings.some((g) => lc(g) === lc(v))) { setIngQ(''); return; }
    setIngs((a) => [...a, v]); setIngQ('');
  };
  const saveRecipe = () => {
    if (!name.trim() || !ings.length) return;
    const isCustom = editingId && store.custom.some((c) => c.id === editingId);
    const isBuiltIn = editingId && (window.RECIPES || []).some((b) => b.id === editingId);
    // editing a built-in hides the original and saves an editable copy
    const id = isCustom ? editingId : 'r_' + Math.random().toString(36).slice(2, 9);
    const r = { id, name: name.trim(), emoji, ingredients: ings.map((n) => ({ name: n })), custom: true };
    update({
      custom: [...store.custom.filter((c) => c.id !== editingId), r],
      removed: isBuiltIn ? [...store.removed, editingId] : store.removed,
    });
    setEditing(false); setEditingId(null); setOpenId(id);
  };

  const fieldStyle = {
    boxSizing: 'border-box', border: `1px solid ${t.color.border}`, outline: 'none',
    background: t.color.surfaceAlt, borderRadius: Math.max(10, t.radius.chip), padding: '11px 13px',
    fontFamily: t.font.body, fontSize: 14.5, fontWeight: 500, color: t.color.text,
  };

  // ── editor mode ───────────────────────────────────────────────────
  if (editing) {
    return (
      <window.Sheet t={t} onClose={() => setEditing(false)} z={56}>
        <div style={{ fontFamily: t.font.head, fontSize: 17, fontWeight: 700, color: t.color.text, marginBottom: 13 }}>{editingId ? tr('editRecipe') : tr('newRecipe')}</div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
          <div style={{ flex: '0 0 auto', width: 46, height: 46, borderRadius: t.radius.chip, background: t.color.surfaceAlt, border: `1px solid ${t.color.border}`, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 24 }}>{emoji}</div>
          <input value={name} onChange={(e) => setName(e.target.value)} autoFocus placeholder={tr('recipeName')}
            style={{ ...fieldStyle, flex: '1 1 auto', minWidth: 0 }} />
        </div>
        <div className="noscroll" style={{ display: 'flex', gap: 4, overflowX: 'auto', marginBottom: 12, paddingBottom: 2 }}>
          {RECIPE_EMOJIS.map((e) => (
            <button key={e} onClick={() => setEmoji(e)} style={{
              flex: '0 0 auto', width: 36, height: 36, borderRadius: t.radius.chip, fontSize: 19, cursor: 'pointer', padding: 0,
              border: e === emoji ? `2px solid ${t.color.accent}` : '1px solid transparent',
              background: e === emoji ? t.color.accentSoft : t.color.surfaceAlt,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>{e}</button>
          ))}
        </div>
        {ings.length > 0 && (
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 10 }}>
            {ings.map((g) => (
              <span key={g} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '6px 8px 6px 11px', borderRadius: t.radius.pill, fontSize: 12.5, fontWeight: 500, background: t.color.accentSoft, color: t.color.accent }}>
                {g}
                <button onClick={() => setIngs((a) => a.filter((x) => x !== g))} aria-label={`remove ${g}`} style={{ border: 'none', background: 'transparent', cursor: 'pointer', padding: 2, display: 'flex' }}>{Ico.x(t.color.accent, 10)}</button>
              </span>
            ))}
          </div>
        )}
        <div style={{ display: 'flex', gap: 8, marginBottom: 14 }}>
          <input value={ingQ} onChange={(e) => setIngQ(e.target.value)} placeholder={tr('addIngredient')}
            onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addIng(); } }}
            style={{ ...fieldStyle, flex: '1 1 auto', minWidth: 0 }} />
          <button onClick={addIng} disabled={!ingQ.trim()} aria-label="add ingredient" style={{
            flex: '0 0 auto', width: 44, borderRadius: Math.max(10, t.radius.chip), border: 'none', cursor: ingQ.trim() ? 'pointer' : 'default',
            background: ingQ.trim() ? t.accentGrad : t.color.surfaceAlt, display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>{Ico.plus(ingQ.trim() ? t.color.accentText : t.color.textFaint, 15)}</button>
        </div>
        <div style={{ display: 'flex', gap: 9 }}>
          <button onClick={() => setEditing(false)} style={{
            flex: '0 0 auto', padding: '12px 16px', borderRadius: t.radius.pill, border: `1px solid ${t.color.border}`,
            background: 'transparent', color: t.color.textMuted, cursor: 'pointer', fontFamily: t.font.head, fontSize: 14, fontWeight: 600,
          }}>{tr('cancel')}</button>
          <button onClick={saveRecipe} disabled={!name.trim() || !ings.length} style={{
            flex: '1 1 auto', padding: '12px 16px', borderRadius: t.radius.pill, border: 'none',
            background: (name.trim() && ings.length) ? t.accentGrad : t.color.surfaceAlt,
            color: (name.trim() && ings.length) ? t.color.accentText : t.color.textFaint,
            cursor: (name.trim() && ings.length) ? 'pointer' : 'default', fontFamily: t.font.head, fontSize: 14, fontWeight: 700,
          }}>{tr('saveRecipe')}</button>
        </div>
      </window.Sheet>
    );
  }

  // ── list mode ─────────────────────────────────────────────────────
  return (
    <window.Sheet t={t} onClose={onClose} z={56}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 13 }}>
        <div style={{ flex: '0 0 auto', width: 40, height: 40, borderRadius: t.radius.chip, background: t.color.accentSoft, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          {Ico.chef(t.color.accent, 21)}
        </div>
        <div style={{ flex: '1 1 auto', fontFamily: t.font.head, fontSize: 17, fontWeight: 700, color: t.color.text }}>{tr('recipes')}</div>
        <button onClick={startNew} style={{
          flex: '0 0 auto', display: 'flex', alignItems: 'center', gap: 6, border: 'none', cursor: 'pointer',
          background: t.accentGrad, color: t.color.accentText, fontFamily: t.font.head, fontSize: 12.5, fontWeight: 700,
          padding: '8px 14px', borderRadius: t.radius.pill, boxShadow: t.shadow.fab,
        }}>{Ico.plus(t.color.accentText, 12)} {tr('newRecipe')}</button>
      </div>
      <div className="noscroll" style={{ display: 'flex', flexDirection: 'column', maxHeight: 380, overflowY: 'auto' }}>
        {recipes.map((r, ri) => {
          const missing = r.ingredients.filter((g) => !present.has(lc(g.name)));
          const inList = r.ingredients.length - missing.length;
          const expanded = openId === r.id;
          const justAdded = addedId === r.id;
          return (
            <div key={r.id} style={{ borderTop: ri > 0 ? `1px solid ${t.color.divider}` : 'none' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 11, padding: '11px 2px' }}>
                <button onClick={() => setOpenId(expanded ? null : r.id)} style={{ flex: '1 1 auto', minWidth: 0, display: 'flex', alignItems: 'center', gap: 11, border: 'none', background: 'transparent', cursor: 'pointer', padding: 0, textAlign: 'start' }}>
                  <span style={{ flex: '0 0 auto', width: 38, height: 38, borderRadius: t.radius.chip, background: t.color.surfaceAlt, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 20 }}>{r.emoji}</span>
                  <span style={{ minWidth: 0 }}>
                    <span style={{ display: 'block', fontFamily: t.font.head, fontSize: 14.5, fontWeight: 700, color: t.color.text, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{trItem(r.name)}</span>
                    <span style={{ display: 'block', fontSize: 12, color: t.color.textFaint, marginTop: 1 }}>
                      {r.ingredients.length} {tr('ingredients')}{inList ? ` · ${inList} ${tr('alreadyIn')}` : ''}
                    </span>
                  </span>
                  <span style={{ flex: '0 0 auto', display: 'inline-flex', marginInlineStart: 'auto', transform: expanded ? 'rotate(180deg)' : 'none', transition: 'transform .18s' }}>{Ico.chevron(t.color.textFaint, 12)}</span>
                </button>
                <button onClick={() => addAll(r, missing)} disabled={!missing.length}
                  style={{
                    flex: '0 0 auto', border: 'none', cursor: missing.length ? 'pointer' : 'default',
                    background: justAdded ? t.color.accentSoft : (missing.length ? t.accentGrad : t.color.surfaceAlt),
                    color: justAdded ? t.color.accent : (missing.length ? t.color.accentText : t.color.textFaint),
                    fontFamily: t.font.head, fontSize: 12, fontWeight: 700, padding: '8px 12px', borderRadius: t.radius.pill,
                    transition: 'background .15s, color .15s', whiteSpace: 'nowrap',
                  }}>
                  {justAdded ? '\u2713 ' + tr('recipeAdded') : (missing.length ? `+ ${missing.length}` : '\u2713')}
                </button>
              </div>
              {expanded && (
                <div style={{ padding: '0 2px 12px 51px' }}>
                  <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                    {r.ingredients.map((g) => {
                      const have = present.has(lc(g.name));
                      return (
                        <span key={g.name} style={{
                          display: 'inline-flex', alignItems: 'center', gap: 5, padding: '5px 10px',
                          borderRadius: t.radius.pill, fontSize: 12, fontWeight: 500,
                          background: have ? t.color.accentSoft : t.color.surfaceAlt,
                          color: have ? t.color.accent : t.color.textMuted,
                          border: `1px solid ${have ? 'transparent' : t.color.divider}`,
                        }}>
                          {have && Ico.check(t.color.accent, 10)}{trItem(g.name)}
                        </span>
                      );
                    })}
                  </div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginTop: 10 }}>
                    <button onClick={() => startEdit(r)} style={{
                      display: 'inline-flex', alignItems: 'center', gap: 6, border: 'none', background: 'transparent',
                      cursor: 'pointer', padding: '3px 0', color: t.color.accent, fontFamily: t.font.head, fontSize: 12.5, fontWeight: 600,
                    }}>{Ico.pencil(t.color.accent, 13)} {tr('editRecipe')}</button>
                    <button onClick={() => deleteRecipe(r)} style={{
                      display: 'inline-flex', alignItems: 'center', gap: 6, border: 'none', background: 'transparent',
                      cursor: 'pointer', padding: '3px 0', color: t.color.danger, fontFamily: t.font.head, fontSize: 12.5, fontWeight: 600,
                    }}>{Ico.trash(t.color.danger, 13)} {tr('deleteRecipe')}</button>
                  </div>
                </div>
              )}
            </div>
          );
        })}
        {recipes.length === 0 && (
          <div style={{ padding: '22px 8px 14px', textAlign: 'center', color: t.color.textFaint, fontSize: 13 }}>{tr('noMatches')}</div>
        )}
      </div>
    </window.Sheet>
  );
}

window.RecipeSheet = RecipeSheet;
})();
