// Saladizer Web — view components.

// ── Helper: compute totals for a selection map { id: qty } ──
// `lookup` is an optional resolver (id => ingredient). Defaults to the
// local mock catalog. Pass a wrapped lookup when extra ingredients have
// been loaded from the server search.
function computeTotals(selections, lookup) {
  const find = lookup || ((id) => ALL_INGREDIENTS.find(i => i.id === id));
  let calories = 0, protein = 0, carbs = 0, fat = 0;
  Object.entries(selections).forEach(([id, qty]) => {
    const ing = find(id);
    if (ing && qty > 0) {
      calories += ing.calories * qty;
      protein  += ing.protein  * qty;
      // Use real USDA macros when available (server-fetched items have them).
      // Fall back to a rough ratio estimate for local-catalog items that lack
      // carbs/fat fields so the displayed values stay roughly sensible.
      carbs    += (ing.carbs != null ? ing.carbs : ing.calories * 0.10) * qty;
      fat      += (ing.fat   != null ? ing.fat   : ing.calories * 0.04) * qty;
    }
  });
  return { calories, protein, carbs, fat };
}

// ── Helper: friendly "X days ago" relative time ────────────
function timeAgo(iso, lang) {
  if (!iso) return '';
  const isAr = lang === 'ar';
  const d = new Date(iso);
  const diffMs = Date.now() - d.getTime();
  const mins = Math.floor(diffMs / 60000);
  if (mins < 1)  return isAr ? 'الآن' : 'Just now';
  if (mins < 60) return isAr ? `قبل ${mins} د` : `${mins}m ago`;
  const hrs = Math.floor(mins / 60);
  if (hrs < 24) return isAr ? `قبل ${hrs} س` : `${hrs}h ago`;
  const days = Math.floor(hrs / 24);
  if (days === 1) return isAr ? 'أمس' : 'Yesterday';
  if (days < 7)  return isAr ? `قبل ${days} أيام` : `${days} days ago`;
  if (days < 30) {
    const w = Math.floor(days / 7);
    return isAr ? `قبل ${w} أسبوع` : `${w} week${w > 1 ? 's' : ''} ago`;
  }
  return isAr ? d.toLocaleDateString('ar-SA') : d.toLocaleDateString('en-US');
}

// ── Helper: pick display name from backend salad ───────────
function saladDisplayName(salad, lang) {
  if (!salad) return '';
  return (lang === 'ar' ? (salad.nameAr || salad.name || salad.nameEn) : (salad.nameEn || salad.name || salad.nameAr)) || '';
}

// ────────────────────────────────────────────────────────────
// DASHBOARD
// ────────────────────────────────────────────────────────────
function DashboardView({ t, lang, onNav, onOpenChef, user, savedSalads }) {
  const [presetDetailId, setPresetDetailId] = React.useState(null);
  const isAr = lang === 'ar';
  const [filter, setFilter] = React.useState('high-protein');
  const [tip, setTip] = React.useState(null);
  const [presets, setPresets] = React.useState([]);

  // Today's macros derived from the most recent saved salad (best signal we have)
  const recent = savedSalads && savedSalads[0];
  const todayCal = recent ? Math.round(recent.totalCalories || 0) : 0;
  const target = (user && user.dailyCalorieTarget) || 2000;
  const macroToday = recent ? {
    p: Math.round(recent.totalProtein || 0),
    c: Math.round(recent.totalCarbs   || 0),
    f: Math.round(recent.totalFat     || 0),
  } : { p: 0, c: 0, f: 0 };
  const macroTarget = { p: 120, c: 250, f: 65 };

  const firstName = (user && (user.fullName || user.username || user.email || '').split(/[\s@]/)[0]) || (isAr ? 'صديقي' : 'friend');

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const d = await window.api.dailyTip();
        if (!cancelled) setTip(d);
      } catch (e) {
        console.warn('[Saladizer] dailyTip failed:', e && (e.status || e.message));
      }
      try {
        const p = await window.api.listFeaturedPresets();
        if (!cancelled) setPresets(Array.isArray(p) ? p : []);
      } catch (e) {
        console.warn('[Saladizer] listFeaturedPresets failed:', e && (e.status || e.message));
      }
    })();
    return () => { cancelled = true; };
  }, []);

  const heroPreset = presets[0] || null;

  return (
    <div className="page">
      <div className="page-eyebrow">{new Date().toLocaleDateString(lang === 'ar' ? 'ar-SA' : 'en-US', { weekday: 'long', month: 'long', day: 'numeric' })}</div>
      <h1 className="page-title">
        {timeGreeting(t)}, {firstName}
        {isAr ? <span className="ar-sub">سعيد لرؤيتك اليوم</span> : null}
      </h1>

      {/* Macro rings */}
      <div className="macro-grid">
        <div className="macro-card">
          <MacroRing value={todayCal} target={target} color="var(--primary)" label={Math.round(todayCal/target*100) + '%'} />
          <div>
            <div className="macro-meta-label">{t.calories}</div>
            <div className="macro-meta-value">{todayCal} <span style={{fontSize:14, color:'var(--fg-muted)', fontWeight:600}}>/ {target}</span></div>
            <div className="macro-meta-target">{Math.max(0, target - todayCal)} {t.cal} {isAr ? 'متبقية' : 'remaining'}</div>
          </div>
        </div>
        <div className="macro-card">
          <MacroRing value={macroToday.p} target={macroTarget.p} color="var(--color-leaf-green)" label={macroToday.p + 'g'} />
          <div>
            <div className="macro-meta-label">{t.protein}</div>
            <div className="macro-meta-value">{macroToday.p}{t.g} <span style={{fontSize:14, color:'var(--fg-muted)', fontWeight:600}}>/ {macroTarget.p}{t.g}</span></div>
            <div className="macro-meta-target">{isAr ? 'على المسار' : 'On track'}</div>
          </div>
        </div>
        <div className="macro-card">
          <MacroRing value={macroToday.c} target={macroTarget.c} color="var(--accent)" label={macroToday.c + 'g'} />
          <div>
            <div className="macro-meta-label">{t.carbs}</div>
            <div className="macro-meta-value">{macroToday.c}{t.g} <span style={{fontSize:14, color:'var(--fg-muted)', fontWeight:600}}>/ {macroTarget.c}{t.g}</span></div>
            <div className="macro-meta-target">{isAr ? 'منخفض' : 'Low'}</div>
          </div>
        </div>
        <div className="macro-card">
          <MacroRing value={macroToday.f} target={macroTarget.f} color="var(--danger)" label={macroToday.f + 'g'} />
          <div>
            <div className="macro-meta-label">{t.fat}</div>
            <div className="macro-meta-value">{macroToday.f}{t.g} <span style={{fontSize:14, color:'var(--fg-muted)', fontWeight:600}}>/ {macroTarget.f}{t.g}</span></div>
            <div className="macro-meta-target">{isAr ? 'صحي' : 'Healthy'}</div>
          </div>
        </div>
      </div>

      {/* Hero card */}
      <div className="hero-card" style={heroPreset && heroPreset.imageUrl ? { backgroundImage: `url('${heroPreset.imageUrl}')` } : null}>
        <div className="hero-card-shade" />
        <div className="hero-card-content">
          <div>
            <span className="hero-card-tag">
              <Icon name="star" size={13} color="#fff" /> {t.saladOfTheDay}
            </span>
          </div>
          <div>
            <div className="hero-card-title" style={{ marginBottom: 18 }}>
              {heroPreset ? saladDisplayName(heroPreset, lang) : (isAr ? 'الطبق المتوسطي بالكينوا' : 'Mediterranean quinoa bowl')}
            </div>
            <div className="hero-card-foot">
              <span className="hero-stat"><Icon name="zap" size={13} color="#fff" /> {heroPreset ? Math.round(heroPreset.totalCalories || 0) : 412} {t.cal}</span>
              <span className="hero-stat"><Icon name="award" size={13} color="#fff" /> {heroPreset ? Math.round(heroPreset.totalProtein || 0) : 22}{t.g} {t.protein}</span>
              <span className="hero-stat"><Icon name="clock" size={13} color="#fff" /> 8 min</span>
              <button className="btn btn-amber btn-sm" style={{ marginInlineStart: 'auto' }} onClick={() => onNav('build')}>
                <Icon name="play" size={13} /> {isAr ? 'حضّر هذا' : 'Make this'}
              </button>
            </div>
          </div>
        </div>
      </div>

      {/* Quick filters */}
      <div className="section-title">
        <h2>{t.quickFilters}</h2>
      </div>
      <div className="chip-row" style={{ marginTop: 0 }}>
        {FILTERS.map(f => (
          <Chip key={f.id} icon={f.icon} label={isAr ? f.ar : f.label} on={filter === f.id} onClick={() => setFilter(f.id)} />
        ))}
      </div>

      <div className="two-up">
        <div className="quick-build">
          <span className="eyebrow-light"><Icon name="zap" size={12} color="rgba(255,255,255,0.78)" /> {isAr ? 'بناء ذكي' : 'Smart build'}</span>
          <h3 style={{ whiteSpace: 'pre-line' }}>{t.quickBuildTitle}</h3>
          <p>{t.quickBuildText}</p>
          <div className="actions">
            <button className="btn btn-amber" onClick={() => onNav('build')}>
              <Icon name="plus" size={16} /> {t.startBuilding}
            </button>
            <button className="btn btn-ghost" style={{ background: 'rgba(255,255,255,0.10)', color: '#fff', borderColor: 'rgba(255,255,255,0.30)' }} onClick={onOpenChef}>
              <Icon name="message-circle" size={16} /> {t.chefsChoice}
            </button>
          </div>
          <svg className="leafs" viewBox="0 0 200 200" aria-hidden="true">
            <path d="M100,20 C140,40 160,80 140,140 C120,180 60,170 40,130 C20,90 60,60 100,20 Z" fill="#fff"/>
            <path d="M100,20 L120,150" stroke="#fff" strokeWidth="2" fill="none" opacity="0.4" />
          </svg>
        </div>

        <div className="tip-card">
          <div className="tip-icon">
            <Icon name="sun" size={24} />
          </div>
          <div>
            <div className="tip-title">{t.tipTitle}</div>
            <div className="tip-body">
              {tip
                ? (isAr ? (tip.tipAr || tip.tip) : (tip.tip || tip.tipAr))
                : t.tipBody}
            </div>
            <div style={{ marginTop: 14, display: 'flex', gap: 8 }}>
              <button className="btn btn-soft btn-sm">
                <Icon name="bookmark" size={14} /> {isAr ? 'احفظ' : 'Save'}
              </button>
              <button className="btn btn-soft btn-sm">
                <Icon name="share-2" size={14} /> {isAr ? 'شارك' : 'Share'}
              </button>
            </div>
          </div>
        </div>
      </div>

      {/* Presets */}
      <div className="section-title">
        <h2>{t.presets}</h2>
        <span className="link" onClick={() => onNav('explore')}>{t.viewAll} →</span>
      </div>
      <div className="preset-grid">
        {(presets.length > 0 ? presets : PRESETS).slice(0, 4).map((p, i) => (
          <PresetCard
            key={p.id || i}
            preset={p}
            t={t}
            lang={lang}
            onClick={() => p.id && typeof p.id !== 'string' ? setPresetDetailId(p.id) : (p.id ? setPresetDetailId(p.id) : onNav('build'))}
          />
        ))}
      </div>

      {/* Chef Makes Me a Salad CTA */}
      <div className="section-title" style={{ marginTop: 32 }}>
        <h2>{t.chefMake}</h2>
      </div>
      <div
        onClick={() => onNav('chefmake')}
        style={{
          cursor: 'pointer', padding: 18, borderRadius: 16,
          background: 'linear-gradient(135deg, var(--primary), var(--color-leaf-green))',
          color: '#fff', display: 'flex', alignItems: 'center', gap: 14,
        }}
      >
        <Icon name="zap" size={28} color="#fff" />
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 800, fontSize: 18 }}>{t.chefMake}</div>
          <div style={{ fontSize: 13, opacity: 0.92 }}>
            {lang === 'ar' ? 'اختر الهدف واترك الشيف يجهّز لك سلطة كاملة.' : 'Pick a goal and let Chef Saladizer compose a complete bowl.'}
          </div>
        </div>
        <Icon name="arrow-right" size={20} color="#fff" />
      </div>

      {/* Recent saved */}
      <div className="section-title">
        <h2>{t.yourRecent}</h2>
        <span className="link" onClick={() => onNav('saved')}>{t.viewAll} →</span>
      </div>
      {savedSalads && savedSalads.length > 0 ? (
        <div className="saved-grid">
          {savedSalads.slice(0, 3).map(s => (
            <SavedCard key={s.id} salad={s} t={t} lang={lang} />
          ))}
        </div>
      ) : (
        <div className="view-loading" style={{ padding: '20px 0' }}>
          {isAr ? 'ما حفظت سلطات بعد. ابدأ من المُكوِّن.' : 'No saved salads yet. Start in the builder.'}
        </div>
      )}

      <PresetDetailModal
        open={presetDetailId !== null}
        onClose={() => setPresetDetailId(null)}
        presetId={presetDetailId}
        lang={lang}
        t={t}
        user={user}
        onBuildFrom={() => onNav('build')}
      />
    </div>
  );
}

function PresetCard({ preset, t, lang, onClick }) {
  const isAr = lang === 'ar';
  // Accept both backend preset shape (nameEn/nameAr/totalCalories/imageUrl) and the local mock shape (name/ar/calories/image).
  const name = saladDisplayName(preset, lang) || (isAr ? preset.ar : preset.name);
  const calories = Math.round(preset.totalCalories ?? preset.calories ?? 0);
  const protein = Math.round(preset.totalProtein ?? preset.protein ?? 0);
  const time = preset.time || '8 min';
  const tag = preset.tag || (Array.isArray(preset.tags) ? preset.tags[0] : null);
  const imageUrl = preset.imageUrl || (preset.image ? 'assets/salad-placeholder.png' : null);

  const photoBg = imageUrl
    ? { backgroundImage: `url('${imageUrl}')` }
    : { background: `linear-gradient(135deg, ${(preset.hue || '#43A047')}cc 0%, ${(preset.hue || '#43A047')} 100%)` };

  return (
    <div className="preset-card" onClick={onClick}>
      <div className="preset-card-photo has-img" style={photoBg}>
        {tag ? (
          <div className="preset-badge">
            <Icon name="star" size={11} color="var(--accent)" /> {tag}
          </div>
        ) : null}
        {!imageUrl ? (
          <div style={{
            position: 'absolute', inset: 0, display: 'flex',
            alignItems: 'center', justifyContent: 'center',
            color: 'rgba(255,255,255,0.55)',
          }}>
            <Icon name="aperture" size={48} color="rgba(255,255,255,0.55)" />
          </div>
        ) : null}
      </div>
      <div className="preset-card-info">
        <div className="preset-card-name">{name}</div>
        <div className="preset-card-meta">
          <Icon name="zap" size={12} color="var(--accent)" />
          <span>{calories} {t.cal}</span>
          <span style={{ color: 'var(--border-strong)' }}>·</span>
          <span>{protein}{t.g} {t.protein}</span>
          <span style={{ color: 'var(--border-strong)' }}>·</span>
          <span>{time}</span>
        </div>
      </div>
    </div>
  );
}

function SavedCard({ salad, t, lang }) {
  const isAr = lang === 'ar';
  // Backend salads have `ingredients` as an array of objects with names embedded.
  // Local mock salads have `ingredients` as an array of string ids that need lookup.
  const ingItems = (salad.ingredients || []).map(item => {
    if (typeof item === 'string') {
      const ing = ALL_INGREDIENTS.find(i => i.id === item);
      return ing ? { name: ing.name, ar: ing.ar } : null;
    }
    if (item && typeof item === 'object') {
      return {
        name: item.nameEn || item.name || '',
        ar: item.nameAr || item.name || '',
      };
    }
    return null;
  }).filter(Boolean);

  const cals = Math.round(salad.totalCalories ?? ingItems.reduce((s, i) => s + (i.calories || 0), 0));
  const prot = Math.round(salad.totalProtein  ?? ingItems.reduce((s, i) => s + (i.protein  || 0), 0));
  const last = salad.lastEaten || timeAgo(salad.updatedAt || salad.createdAt, lang);
  const displayName = saladDisplayName(salad, lang) || (isAr ? salad.ar : salad.name);

  return (
    <div className="saved-card">
      <div className="saved-card-head">
        <div className="saved-card-icon"><Icon name="aperture" size={22} /></div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="saved-card-name">{displayName}</div>
          <div className="saved-card-meta">{ingItems.length} {t.items}</div>
        </div>
        <button className="icon-btn" style={{ width: 34, height: 34, background: 'transparent' }}>
          <Icon name="more-horizontal" size={18} />
        </button>
      </div>
      <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
        {ingItems.slice(0, 5).map((i, idx) => (
          <span key={idx} style={{
            fontSize: 12, fontWeight: 600,
            background: 'var(--bg-tinted)', color: 'var(--fg)',
            padding: '4px 9px', borderRadius: 9999,
          }}>
            {isAr ? (i.ar || i.name) : (i.name || i.ar)}
          </span>
        ))}
        {ingItems.length > 5 && (
          <span style={{ fontSize: 12, color: 'var(--fg-muted)', padding: '4px 0' }}>+{ingItems.length - 5}</span>
        )}
      </div>
      <div className="saved-card-foot">
        <span><strong>{cals}</strong> {t.cal}</span>
        <span><strong>{prot}{t.g}</strong> {t.protein}</span>
        <span style={{ marginInlineStart: 'auto', color: 'var(--fg-muted)' }}>{last}</span>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// BUILDER
// ────────────────────────────────────────────────────────────
function BuilderView({ t, lang, selections, setSelections, onSave, onOpenChef, saladName, setSaladName, user, extraCatalog: extraCatalogProp, setExtraCatalog: setExtraCatalogProp, initialSearch, onInitialSearchConsumed, fromChef, chefNote, chefNutrition, onLeaveChefMode }) {
  const [activeCat, setActiveCat] = React.useState('Greens');
  const [ingSearch, setIngSearch] = React.useState(initialSearch || '');
  // When arriving from Chef Makes Me a Salad the ingredient grid starts collapsed.
  const [showIngGrid, setShowIngGrid] = React.useState(!fromChef);
  React.useEffect(() => {
    if (initialSearch) {
      setIngSearch(initialSearch);
      if (onInitialSearchConsumed) onInitialSearchConsumed();
    }
  }, [initialSearch]);
  // If fromChef changes (e.g. user navigates back to chef) re-sync collapsed state.
  React.useEffect(() => { setShowIngGrid(!fromChef); }, [fromChef]);
  const [aiBusy, setAiBusy] = React.useState(null); // 'name' | 'suggest' | 'image' | null
  const [aiToast, setAiToast] = React.useState('');
  const [suggestions, setSuggestions] = React.useState([]);
  const [generatedImage, setGeneratedImage] = React.useState(null);
  const [shareOpen, setShareOpen] = React.useState(false);
  const [allergenAlert, setAllergenAlert] = React.useState(null); // { name, replacement }
  // Server-side ingredients the user has interacted with this session.
  // Keyed by id so totals / lists can resolve them once they leave the search.
  // Lifted to App so the Chef-makes-me-a-salad view can hand off extras.
  const [extraCatalogLocal, setExtraCatalogLocal] = React.useState({});
  const extraCatalog = extraCatalogProp || extraCatalogLocal;
  const setExtraCatalog = setExtraCatalogProp || setExtraCatalogLocal;
  const lookup = React.useCallback(
    (id) => extraCatalog[id] || ALL_INGREDIENTS.find(i => i.id === id),
    [extraCatalog]
  );
  const totals = React.useMemo(() => computeTotals(selections, lookup), [selections, lookup]);
  // While in "from chef" mode, surface the chef AI's own estimatedNutrition so
  // the builder shows the exact same numbers the user just saw on the chef
  // result card. Computed USDA totals never match the chef's own estimate.
  const displayTotals = (fromChef && chefNutrition)
    ? {
        calories: Number(chefNutrition.calories) || 0,
        protein:  Number(chefNutrition.protein)  || 0,
        carbs:    Number(chefNutrition.carbs)    || 0,
        fat:      Number(chefNutrition.fat)      || 0,
      }
    : totals;
  // Once the user modifies the chef-generated selections, drop chef-mode so
  // they see honest computed totals from their edited list (and the chef
  // explanation panel disappears).
  const initialChefSelectionsRef = React.useRef(null);
  React.useEffect(() => {
    if (fromChef && initialChefSelectionsRef.current === null) {
      initialChefSelectionsRef.current = JSON.stringify(selections);
    } else if (!fromChef) {
      initialChefSelectionsRef.current = null;
    } else if (initialChefSelectionsRef.current !== JSON.stringify(selections)) {
      if (onLeaveChefMode) onLeaveChefMode();
      initialChefSelectionsRef.current = null;
    }
  }, [fromChef, selections, onLeaveChefMode]);
  const items = React.useMemo(() => Object.entries(selections)
    .map(([id, qty]) => ({ ing: lookup(id), qty }))
    .filter(x => x.ing && x.qty > 0)
  , [selections, lookup]);

  // Debounced server search (USDA + chef). Local catalog is still used
  // for 1-char queries and category browse so the UI stays snappy.
  const search = useDebouncedIngredientSearch(ingSearch, { minChars: 2, debounceMs: 250, limit: 30 });

  const totalCount = Object.values(selections).reduce((a, b) => a + b, 0);
  const isAr = lang === 'ar';

  function flashToast(msg, ms = 2500) {
    setAiToast(msg);
    setTimeout(() => setAiToast(''), ms);
  }

  async function aiGenerateName() {
    if (items.length === 0) return;
    setAiBusy('name');
    try {
      const r = await window.api.generateNameCategory({
        ingredients: items.map(({ ing }) => ing.name),
        ingredientsAr: items.map(({ ing }) => ing.ar),
        category: 'artistic',
        language: isAr ? 'ar' : 'en',
      });
      const name = (r?.names && r.names[0]) || null;
      if (name) setSaladName(isAr ? (name.ar || name.en) : (name.en || name.ar));
    } catch (e) {
      console.error('[Saladizer] generateName failed:', e);
      flashToast(
        e && e.status === 403
          ? (isAr ? 'هذه الميزة لمشتركي Plus' : 'Plus members only')
          : (isAr ? 'تعذّر توليد الاسم' : 'Could not generate name')
      );
    } finally { setAiBusy(null); }
  }

  async function aiSuggestIngredients() {
    setAiBusy('suggest');
    setSuggestions([]);
    try {
      const r = await window.api.suggestIngredients({
        ingredients: items.map(({ ing }) => ing.name),
        ingredientsAr: items.map(({ ing }) => ing.ar),
        nutrition: { calories: totals.calories, protein: totals.protein },
        useGoalBased: true,
      });
      const s = Array.isArray(r?.suggestions) ? r.suggestions : [];
      setSuggestions(s);
      if (r?.isRateLimited) {
        flashToast(isAr ? 'وصلت الحد اليومي. جرّب لاحقاً.' : 'Daily limit reached.');
      } else if (s.length === 0) {
        flashToast(isAr ? 'لا توجد اقتراحات الآن' : 'No suggestions right now');
      }
    } catch (e) {
      console.error('[Saladizer] suggestIngredients failed:', e);
      flashToast(isAr ? 'تعذّر جلب الاقتراحات' : 'Could not get suggestions');
    } finally { setAiBusy(null); }
  }

  async function aiGenerateImage() {
    if (items.length === 0) return;
    setAiBusy('image');
    setGeneratedImage(null);
    try {
      const r = await window.api.generateSaladImage({
        ingredientsEn: items.map(({ ing }) => ing.name),
        saladName: saladName || undefined,
      });
      if (r?.success && r.imageUrl) {
        setGeneratedImage(r.imageUrl);
      } else if (r?.isLimited) {
        flashToast(isAr ? (r.messageAr || 'وصلت الحد اليومي للصور') : (r.messageEn || 'Daily image limit reached'));
      } else {
        flashToast(isAr ? (r?.messageAr || 'تعذّر توليد الصورة') : (r?.messageEn || 'Could not generate image'));
      }
    } catch (e) {
      console.error('[Saladizer] generateImage failed:', e);
      flashToast(
        e && e.status === 403
          ? (isAr ? 'توليد الصور لمشتركي Plus' : 'Image generation is Plus only')
          : (isAr ? 'تعذّر توليد الصورة' : 'Could not generate image')
      );
    } finally { setAiBusy(null); }
  }

  const update = (id, delta) => setSelections(prev => {
    const next = { ...prev, [id]: Math.max(0, (prev[id] || 0) + delta) };
    if (next[id] === 0) delete next[id];
    return next;
  });

  // Apply an AI suggestion: try to match by English name against ALL_INGREDIENTS.
  function applySuggestion(s) {
    const en = (s && (s.name || s.nameEn || s.ingredient || (typeof s === 'string' ? s : ''))) || '';
    const ar = (s && (s.nameAr || s.ar)) || '';
    if (!en && !ar) return;
    const match = ALL_INGREDIENTS.find(x =>
      x.name.toLowerCase() === en.toLowerCase() ||
      x.ar.toLowerCase() === ar.toLowerCase()
    );
    if (match) {
      setSelections(prev => ({ ...prev, [match.id]: (prev[match.id] || 0) + 1 }));
      flashToast(isAr ? `أُضيف: ${match.ar}` : `Added: ${match.name}`);
    } else {
      flashToast(isAr ? 'هذا المكون غير موجود في القائمة' : 'Ingredient not in catalog');
    }
  }

  // Allergen auto-check: whenever selections change, look for any selected
  // ingredient whose name matches a profile allergen and ask the AI for a
  // replacement.
  const lastAllergenCheck = React.useRef('');
  React.useEffect(() => {
    if (!user || !Array.isArray(user.allergens) || user.allergens.length === 0) return;
    const lowerAllergens = user.allergens.map(a => String(a).toLowerCase());
    const hit = items.find(({ ing }) => lowerAllergens.some(a => ing.name.toLowerCase().includes(a) || ing.ar.includes(a)));
    if (!hit) { setAllergenAlert(null); return; }
    const key = hit.ing.id + '|' + lowerAllergens.join(',');
    if (lastAllergenCheck.current === key) return;
    lastAllergenCheck.current = key;
    (async () => {
      try {
        const r = await window.api.findAllergenReplacement({
          ingredient: hit.ing.name,
          ingredientAr: hit.ing.ar,
          allergen: user.allergens[0],
          currentIngredients: items.map(({ ing }) => ing.name),
          language: isAr ? 'ar' : 'en',
        });
        if (r && (r.replacement || r.suggestion)) {
          setAllergenAlert({
            offending: isAr ? hit.ing.ar : hit.ing.name,
            replacement: r.replacement || r.suggestion,
            offendingId: hit.ing.id,
          });
        }
      } catch (_) {}
    })();
  }, [items, user, isAr]);

  function applyAllergenReplacement() {
    if (!allergenAlert) return;
    applySuggestion({
      name: allergenAlert.replacement.nameEn || allergenAlert.replacement.name,
      nameAr: allergenAlert.replacement.nameAr,
    });
    // Remove the offending ingredient.
    setSelections(prev => {
      const next = { ...prev };
      delete next[allergenAlert.offendingId];
      return next;
    });
    setAllergenAlert(null);
  }

  const catCounts = React.useMemo(() => {
    const c = {};
    Object.entries(selections).forEach(([id, qty]) => {
      const ing = lookup(id);
      if (ing && qty > 0) c[ing.category] = (c[ing.category] || 0) + qty;
    });
    return c;
  }, [selections, lookup]);

  return (
    <div className="page">
      <div className="page-eyebrow">
        {fromChef
          ? (isAr ? 'الشيف يصنع لي سلطة' : 'Chef makes me a salad')
          : t.builderTitle}
      </div>
      <h1 className="page-title">
        {fromChef
          ? (isAr ? 'سلطتك جاهزة!' : 'Your salad is ready!')
          : (isAr ? 'اصنع سلطتك' : 'Make it yours.')}
        {!fromChef && !isAr ? <span style={{ display: 'block', color: 'var(--fg-muted)', fontSize: 18, fontWeight: 600, marginTop: 8 }}>{t.builderSub}</span> : null}
      </h1>

      {fromChef ? (
        <div style={{ marginTop: 10, marginBottom: 4, display: 'flex', justifyContent: 'flex-start' }}>
          <button
            type="button"
            className="btn btn-soft btn-sm"
            onClick={() => {
              setShowIngGrid(v => !v);
              if (onLeaveChefMode && !showIngGrid) onLeaveChefMode();
            }}
            style={{ gap: 6 }}
          >
            <Icon name={showIngGrid ? 'eye-off' : 'edit-2'} size={13} />
            {showIngGrid
              ? (isAr ? 'إخفاء قائمة المكونات' : 'Hide ingredient list')
              : (isAr ? 'تعديل المكونات' : 'Edit ingredients')}
          </button>
        </div>
      ) : null}

      <div className="builder" style={{ marginTop: fromChef ? 12 : 28 }}>
        {showIngGrid ? (<div className="builder-main">
          <div className="builder-search" style={{
            position: 'relative', marginBottom: 16,
          }}>
            <span style={{
              position: 'absolute', top: '50%', transform: 'translateY(-50%)',
              [isAr ? 'right' : 'left']: 14, display: 'inline-flex',
              color: 'var(--fg-muted)', pointerEvents: 'none',
            }}>
              <Icon name="search" size={16} />
            </span>
            <input
              type="text"
              value={ingSearch}
              onChange={(e) => setIngSearch(e.target.value)}
              placeholder={isAr ? 'ابحث عن مكون...' : 'Search ingredients...'}
              style={{
                width: '100%', height: 42,
                padding: isAr ? '0 40px 0 14px' : '0 14px 0 40px',
                borderRadius: 9999,
                border: '1.5px solid var(--border)',
                background: 'var(--bg-surface)',
                color: 'var(--fg)', fontSize: 14, fontFamily: 'inherit',
                outline: 'none',
              }}
            />
          </div>

          {ingSearch.trim() ? null : (
            <div className="builder-cats">
              {CATEGORIES.map(cat => (
                <button
                  key={cat}
                  className={'builder-cat' + (activeCat === cat ? ' on' : '')}
                  onClick={() => setActiveCat(cat)}
                >
                  {cat === 'Greens'     && <Icon name="feather" size={14} />}
                  {cat === 'Vegetables' && <Icon name="circle"  size={14} />}
                  {cat === 'Protein'    && <Icon name="zap"     size={14} />}
                  {cat === 'Toppings'   && <Icon name="star"    size={14} />}
                  {cat === 'Dressing'   && <Icon name="droplet" size={14} />}
                  {isAr ? translateCat(cat) : cat}
                  {catCounts[cat] ? <span className="count">{catCounts[cat]}</span> : null}
                </button>
              ))}
            </div>
          )}

          <div className="ing-grid">
            {(() => {
              const qRaw = ingSearch.trim();
              const q = qRaw.toLowerCase();
              // 1-char queries: still use the local catalog (fast, avoids
              // huge server responses). 2+ chars: use server search.
              let list;
              let usingServer = false;
              if (q.length >= 2) {
                usingServer = true;
                list = search.items;
              } else if (q.length === 1) {
                list = ALL_INGREDIENTS.filter(i =>
                  (i.name || '').toLowerCase().includes(q) ||
                  (i.ar || '').includes(qRaw)
                );
              } else {
                list = (INGREDIENTS[activeCat] || []);
              }
              if (usingServer && search.loading && list.length === 0) {
                return (
                  <div style={{ gridColumn: '1 / -1', textAlign: 'center', padding: 24, color: 'var(--fg-muted)', fontSize: 14 }}>
                    {isAr ? 'جارٍ البحث…' : 'Searching…'}
                  </div>
                );
              }
              if (usingServer && search.error && list.length === 0) {
                return (
                  <div style={{ gridColumn: '1 / -1', textAlign: 'center', padding: 24, color: 'var(--danger)', fontSize: 14 }}>
                    {isAr ? 'تعذّر البحث، حاول مرة أخرى' : 'Search failed, try again'}
                  </div>
                );
              }
              if (q && list.length === 0) {
                return (
                  <div style={{ gridColumn: '1 / -1', textAlign: 'center', padding: 24, color: 'var(--fg-muted)', fontSize: 14 }}>
                    {isAr ? 'لا توجد نتائج' : 'No matches'}
                  </div>
                );
              }
              const addFromCatalog = (ing) => {
                if (usingServer) {
                  setExtraCatalog(prev => prev[ing.id] ? prev : { ...prev, [ing.id]: ing });
                }
                update(ing.id, +1);
              };
              return list.map(ing => {
              const qty = selections[ing.id] || 0;
              return (
                <div key={ing.id} className={'ing-card' + (qty > 0 ? ' has' : '')}>
                  <div className="ing-thumb">{ing.glyph}</div>
                  <div className="ing-info">
                    <div className="ing-name">
                      {isAr ? ing.ar : ing.name}
                      {ing.custom || ing.isChef ? (
                        <span className="custom-pill">
                          <Icon name="user" size={9} /> {ing.isChef ? (isAr ? 'شيف' : 'chef') : (isAr ? 'مخصص' : 'custom')}
                        </span>
                      ) : null}
                    </div>
                    <div className="ing-meta">{Math.round(ing.calories)} {t.cal} · {Math.round(ing.protein * 10) / 10}{t.g} {t.protein}</div>
                  </div>
                  <div className="ing-qty-controls">
                    <button className="qty-btn minus" disabled={qty === 0} onClick={() => update(ing.id, -1)}>
                      <Icon name="minus" size={16} color={qty > 0 ? '#fff' : 'var(--danger)'} />
                    </button>
                    <span className="qty-num">{qty}</span>
                    <button className="qty-btn plus" onClick={() => addFromCatalog(ing)}>
                      <Icon name="plus" size={16} color="#fff" />
                    </button>
                  </div>
                </div>
              );
            });
            })()}
          </div>
        </div>) : null}

        <div className="builder-rail">
          <div style={{ display: 'flex', gap: 6 }}>
            <input
              className="salad-name-input"
              type="text"
              value={saladName}
              placeholder={t.saladName}
              onChange={(e) => setSaladName(e.target.value)}
              style={{ flex: 1 }}
            />
            {!fromChef ? (
              <button
                type="button"
                className="btn btn-soft btn-sm"
                title={isAr ? 'توليد اسم بالذكاء' : 'AI name'}
                disabled={totalCount === 0 || aiBusy === 'name'}
                onClick={aiGenerateName}
              >
                <Icon name="zap" size={14} />
                {aiBusy === 'name' ? '…' : 'AI'}
              </button>
            ) : null}
          </div>

          <div className="bowl" style={generatedImage ? { backgroundImage: `url('${generatedImage}')`, backgroundSize: 'cover', backgroundPosition: 'center' } : null}>
            {!generatedImage && <BowlPreview items={items} />}
            <div className="bowl-overlay">
              {totalCount === 0 ? (
                <>
                  <div className="bowl-cal" style={{ color: 'var(--fg-muted)' }}>0</div>
                  <div className="bowl-cal-label">{t.cal}</div>
                </>
              ) : (
                <>
                  <div className="bowl-cal">{Math.round(displayTotals.calories)}</div>
                  <div className="bowl-cal-label">{t.cal}</div>
                </>
              )}
            </div>
          </div>

          {fromChef && chefNote ? (
            <div style={{
              background: 'var(--bg-tinted)', borderRadius: 12, padding: '10px 12px',
              borderLeft: isAr ? undefined : '3px solid var(--primary)',
              borderRight: isAr ? '3px solid var(--primary)' : undefined,
            }}>
              <div style={{ fontSize: 11, fontWeight: 800, color: 'var(--primary)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 6 }}>
                <Icon name="message-circle" size={11} color="var(--primary)" /> {isAr ? 'لماذا هذه السلطة؟' : 'Why this salad?'}
              </div>
              <ul style={{ margin: 0, padding: isAr ? '0 14px 0 0' : '0 0 0 14px' }}>
                {(isAr ? chefNote.ar : chefNote.en).map((line, i) => (
                  <li key={i} style={{ fontSize: 12, color: 'var(--fg-muted)', marginBottom: 3 }}>{line}</li>
                ))}
              </ul>
            </div>
          ) : null}

          <div className="ai-actions">
            {!fromChef ? (
              <button type="button" className="btn btn-soft btn-sm" disabled={aiBusy === 'suggest'} onClick={aiSuggestIngredients}>
                <Icon name="zap" size={12} /> {aiBusy === 'suggest' ? (isAr ? 'جارٍ...' : 'Working…') : (isAr ? 'اقتراحات' : 'AI suggest')}
              </button>
            ) : null}
            <button type="button" className="btn btn-soft btn-sm" disabled={totalCount === 0 || aiBusy === 'image'} onClick={aiGenerateImage}>
              <Icon name="image" size={12} /> {aiBusy === 'image' ? (isAr ? 'جارٍ...' : 'Working…') : (isAr ? 'صورة AI' : 'AI image')}
            </button>
          </div>

          {suggestions.length > 0 ? (
            <div style={{ background: 'var(--bg-tinted)', borderRadius: 12, padding: '10px 12px' }}>
              <div style={{ fontSize: 11, fontWeight: 800, color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 8 }}>
                {isAr ? 'اقتراحات الذكاء' : 'AI suggestions'}
              </div>
              <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 6 }}>
                {suggestions.slice(0, 5).map((s, i) => {
                  const label = isAr
                    ? (s.nameAr || s.name || s.ingredient || s)
                    : (s.name || s.nameEn || s.ingredient || s);
                  return (
                    <li key={i} style={{ fontSize: 13, color: 'var(--fg)', display: 'flex', alignItems: 'center', gap: 8 }}>
                      <span style={{ flex: 1 }}>{String(label)}</span>
                      <button
                        type="button"
                        className="btn btn-soft btn-sm"
                        onClick={() => applySuggestion(s)}
                        style={{ padding: '4px 10px', fontSize: 11 }}
                      >
                        <Icon name="plus" size={11} color="var(--primary)" /> {t.apply}
                      </button>
                    </li>
                  );
                })}
              </ul>
            </div>
          ) : null}

          {allergenAlert ? (
            <div className="warn-box" style={{
              background: 'rgba(244, 67, 54, 0.08)', border: '1px solid rgba(244, 67, 54, 0.3)',
              borderRadius: 12, padding: '10px 12px',
            }}>
              <div style={{ fontWeight: 700, fontSize: 13, color: 'var(--danger)', marginBottom: 6 }}>
                <Icon name="alert-triangle" size={12} color="var(--danger)" /> {isAr ? 'تنبيه حساسية' : 'Allergen alert'}
              </div>
              <div style={{ fontSize: 12, color: 'var(--fg-muted)', marginBottom: 8 }}>
                {isAr
                  ? `قد تكون لديك حساسية من ${allergenAlert.offending}. الشيف يقترح ${allergenAlert.replacement.nameAr || allergenAlert.replacement.name}.`
                  : `${allergenAlert.offending} may trigger your allergens. Chef suggests ${allergenAlert.replacement.nameEn || allergenAlert.replacement.name}.`}
              </div>
              <div style={{ display: 'flex', gap: 6 }}>
                <button className="btn btn-primary btn-sm" onClick={applyAllergenReplacement} style={{ fontSize: 11 }}>
                  {isAr ? 'استبدل' : 'Swap'}
                </button>
                <button className="btn btn-soft btn-sm" onClick={() => setAllergenAlert(null)} style={{ fontSize: 11 }}>
                  {isAr ? 'تجاهل' : 'Dismiss'}
                </button>
              </div>
            </div>
          ) : null}

          {aiToast ? (
            <div style={{ fontSize: 12, color: 'var(--fg-muted)', textAlign: 'center' }}>{aiToast}</div>
          ) : null}

          <div className="macro-bars">
            <MacroBar label={t.protein} value={displayTotals.protein} target={60} unit={t.g} color="var(--primary)" />
            <MacroBar label={t.carbs}   value={displayTotals.carbs}   target={80} unit={t.g} color="var(--accent)"   className="amber" />
            <MacroBar label={t.fat}     value={displayTotals.fat}     target={40} unit={t.g} color="var(--danger)"   className="carrot" />
          </div>

          <div style={{ borderTop: '1px solid var(--border)', paddingTop: 14 }}>
            <div style={{ fontSize: 11, fontWeight: 800, color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.10em', marginBottom: 10 }}>
              {t.ingredients}{totalCount > 0 ? ` (${totalCount})` : ''}
            </div>
            {items.length === 0 ? (
              <div className="empty-bowl">{t.emptyBowl}</div>
            ) : (
              <ul className="ing-list">
                {items.map(({ ing, qty }) => (
                  <li key={ing.id}>
                    <span className="dot" style={{ background: ingredientColor(ing) }} />
                    <span>{isAr ? ing.ar : ing.name}</span>
                    <span className="qty">×{qty}</span>
                  </li>
                ))}
              </ul>
            )}
          </div>

          <div className="rail-actions">
            <button className="btn btn-primary" disabled={totalCount === 0} onClick={() => onSave(items, totals)}>
              <Icon name="bookmark" size={16} /> {t.saveSalad}
            </button>
            <button className="btn btn-soft" onClick={onOpenChef}>
              <Icon name="message-circle" size={16} /> {t.askChef}
            </button>
            <button className="btn btn-soft" disabled={totalCount === 0} onClick={() => setShareOpen(true)}>
              <Icon name="share-2" size={16} /> {t.share}
            </button>
          </div>
        </div>
      </div>

      <ShareSaladModal
        open={shareOpen}
        onClose={() => setShareOpen(false)}
        lang={lang}
        selections={selections}
        saladName={saladName}
        totals={totals}
      />
    </div>
  );
}

function translateCat(cat) {
  return ({ Greens: 'الأخضر', Vegetables: 'الخضار', Protein: 'البروتين', Toppings: 'الإضافات', Dressing: 'التتبيلة' })[cat] || cat;
}

function MacroBar({ label, value, target, unit, color, className }) {
  const pct = Math.min(100, (value / target) * 100);
  return (
    <div className="macro-bar">
      <div className="macro-bar-label">{label}</div>
      <div className="macro-bar-track">
        <div className={'macro-bar-fill ' + (className || '')} style={{ width: pct + '%', background: color }} />
      </div>
      <div className="macro-bar-value">{value.toFixed(1)}{unit}</div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// EXPLORE
// ────────────────────────────────────────────────────────────
function ExploreView({ t, lang, onNav, user }) {
  const [activeFilter, setActiveFilter] = React.useState('all');
  const [presets, setPresets] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [err, setErr] = React.useState('');
  const [presetDetailId, setPresetDetailId] = React.useState(null);
  const isAr = lang === 'ar';

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const list = await window.api.listPresetSalads();
        if (!cancelled) setPresets(Array.isArray(list) ? list : []);
      } catch (e) {
        console.error('[Saladizer] listPresetSalads failed:', e && (e.status || e.message), e);
        if (!cancelled) setErr((isAr ? 'تعذّر تحميل السلطات' : 'Could not load salads') + (e && e.status ? ` (HTTP ${e.status})` : ''));
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, [isAr]);

  // Filter by tag/category
  const filtered = activeFilter === 'all'
    ? presets
    : presets.filter(p => {
        const tags = (p.tags || []).map(s => String(s).toLowerCase());
        const cat = (p.category || '').toLowerCase();
        const map = {
          'high-protein': ['high-protein', 'high protein', 'protein'],
          'vegan':        ['vegan'],
          'keto':         ['keto'],
          'quick':        ['quick', 'fast'],
          'local':        ['local', 'saudi', 'arab'],
          'low-cal':      ['low-cal', 'light', 'low calorie'],
        };
        const want = map[activeFilter] || [];
        return want.some(w => tags.includes(w) || cat.includes(w));
      });

  return (
    <div className="page">
      <div className="page-eyebrow">{isAr ? 'استكشف' : 'Explore'}</div>
      <h1 className="page-title">
        {t.exploreTitle}
        <span style={{ display: 'block', color: 'var(--fg-muted)', fontSize: 18, fontWeight: 600, marginTop: 8 }}>{t.exploreSub}</span>
      </h1>

      <div className="chip-row" style={{ marginTop: 28 }}>
        <Chip icon="grid" label={isAr ? 'الكل' : 'All'} on={activeFilter === 'all'} onClick={() => setActiveFilter('all')} />
        {FILTERS.map(f => (
          <Chip key={f.id} icon={f.icon} label={isAr ? f.ar : f.label} on={activeFilter === f.id} onClick={() => setActiveFilter(f.id)} />
        ))}
      </div>

      {loading ? (
        <div className="view-loading">{isAr ? 'جارٍ التحميل...' : 'Loading salads...'}</div>
      ) : err ? (
        <div className="view-error">{err}</div>
      ) : filtered.length === 0 ? (
        <div className="view-loading">{isAr ? 'ما فيه سلطات مطابقة لهذا الفلتر.' : 'No salads match this filter yet.'}</div>
      ) : (
        <div className="preset-grid" style={{ marginTop: 24 }}>
          {filtered.map(p => (
            <PresetCard key={p.id} preset={p} t={t} lang={lang} onClick={() => p.id ? setPresetDetailId(p.id) : onNav('build')} />
          ))}
        </div>
      )}

      <PresetDetailModal
        open={presetDetailId !== null}
        onClose={() => setPresetDetailId(null)}
        presetId={presetDetailId}
        lang={lang}
        t={t}
        user={user}
        onBuildFrom={() => onNav('build')}
      />
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// SAVED
// ────────────────────────────────────────────────────────────
function SavedView({ t, lang, savedSalads, loading, onNav, onReload }) {
  const isAr = lang === 'ar';

  async function handleDelete(id) {
    if (!confirm(isAr ? 'حذف هذه السلطة؟' : 'Delete this salad?')) return;
    try {
      await window.api.deleteSalad(id);
      if (onReload) await onReload();
    } catch (_) {}
  }

  return (
    <div className="page">
      <div className="page-eyebrow">{isAr ? 'محفوظاتك' : 'Your saved'}</div>
      <h1 className="page-title">
        {t.saved}
        <span style={{ display: 'block', color: 'var(--fg-muted)', fontSize: 18, fontWeight: 600, marginTop: 8 }}>
          {savedSalads.length} {isAr ? 'سلطة جاهزة لتعيدها' : 'salads ready to remix.'}
        </span>
      </h1>

      {loading ? (
        <div className="view-loading">{isAr ? 'جارٍ التحميل...' : 'Loading your salads...'}</div>
      ) : savedSalads.length === 0 ? (
        <div style={{ textAlign: 'center', padding: '80px 20px' }}>
          <img src="assets/empty-salads.png" alt="" style={{ width: 180, height: 180, objectFit: 'contain', opacity: 0.85 }} />
          <h3 style={{ fontWeight: 700, fontSize: 20, color: 'var(--fg)', margin: '8px 0' }}>{t.notFound}</h3>
          <p style={{ color: 'var(--fg-muted)', maxWidth: 360, margin: '0 auto 18px' }}>{t.notFoundSub}</p>
          <button className="btn btn-primary" onClick={() => onNav('build')}>{t.startBuilding}</button>
        </div>
      ) : (
        <div className="saved-grid" style={{ marginTop: 28 }}>
          {savedSalads.map(s => (
            <SavedCardWithActions key={s.id} salad={s} t={t} lang={lang} onDelete={() => handleDelete(s.id)} />
          ))}
        </div>
      )}
    </div>
  );
}

function SavedCardWithActions({ salad, t, lang, onDelete }) {
  const [menuOpen, setMenuOpen] = React.useState(false);
  return (
    <div style={{ position: 'relative' }}>
      <SavedCard salad={salad} t={t} lang={lang} />
      {menuOpen && (
        <div
          onClick={() => setMenuOpen(false)}
          style={{
            position: 'absolute', top: 50,
            insetInlineEnd: 12,
            background: 'var(--bg-elevated)',
            border: '1px solid var(--border)',
            borderRadius: 12,
            boxShadow: 'var(--shadow-card-hover)',
            padding: 6,
            zIndex: 10,
          }}
        >
          <button
            className="btn btn-soft btn-sm"
            style={{ width: '100%', justifyContent: 'flex-start' }}
            onClick={onDelete}
          >
            <Icon name="trash-2" size={14} /> {lang === 'ar' ? 'حذف' : 'Delete'}
          </button>
        </div>
      )}
      <button
        onClick={() => setMenuOpen(o => !o)}
        style={{
          position: 'absolute', top: 16,
          insetInlineEnd: 16,
          width: 34, height: 34,
          border: 'none', background: 'transparent', cursor: 'pointer',
          color: 'var(--fg-muted)',
        }}
        aria-label="actions"
      >
        <Icon name="more-horizontal" size={18} />
      </button>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// PROFILE
// ────────────────────────────────────────────────────────────
function ProfileView({ t, lang, setLang, tweak, setTweak, user, setUser, savedSalads, onLogout, onAccountDeleted }) {
  const isAr = lang === 'ar';
  const [profile, setProfile] = React.useState(null);
  const [modal, setModal] = React.useState(null); // 'info' | 'goals' | 'diet' | 'allergens' | 'language' | 'password' | 'delete'

  const reloadProfile = React.useCallback(async () => {
    try {
      const p = await window.api.getProfile();
      setProfile(p);
    } catch (e) {
      console.warn('[Saladizer] getProfile failed:', e && (e.status || e.message));
    }
  }, []);

  React.useEffect(() => { reloadProfile(); }, [reloadProfile]);

  function onProfileSaved(updated) {
    // Server returns either the merged user (auth fields) or the merged profile.
    if (updated && (updated.fullName !== undefined || updated.profileImageUri !== undefined) && setUser) {
      setUser(u => ({ ...(u || {}), ...updated }));
    }
    reloadProfile();
  }

  const displayName = (user && (user.fullName || user.username)) || (isAr ? 'مستخدم' : 'User');
  const email = (user && user.email) || '';
  const isPlus = user && user.subscriptionType && user.subscriptionType !== 'free';
  const isAdmin = user && user.role === 'admin';
  const totalCalsSaved = savedSalads.reduce((s, x) => s + (x.totalCalories || 0), 0);

  const stats = [
    { v: String(savedSalads.length), l: t.salads },
    { v: totalCalsSaved >= 1000 ? `${(totalCalsSaved/1000).toFixed(1)}k` : String(Math.round(totalCalsSaved)), l: t.calStat },
    { v: profile ? String(Math.max(1, savedSalads.length)) : '0', l: t.streak },
  ];

  const dietParts = [];
  if (profile?.isVegetarian)  dietParts.push(isAr ? 'نباتي' : 'Vegetarian');
  if (profile?.isKeto)        dietParts.push(isAr ? 'كيتو' : 'Keto');
  if (profile?.isLowSodium)   dietParts.push(isAr ? 'صوديوم منخفض' : 'Low sodium');
  if (profile?.noAddedSugar)  dietParts.push(isAr ? 'بدون سكر' : 'No sugar');
  const dietLabel = dietParts.length ? dietParts.join(' · ') : (isAr ? 'بدون قيود' : 'No restrictions');

  const allergensCount = (profile?.allergens || []).length;
  const calorieTarget = profile?.dailyCalorieTarget || 2000;

  const editableRows = [
    { key: 'info',      icon: 'edit-2',       label: isAr ? 'المعلومات الشخصية' : 'Personal info',  value: displayName },
    { key: 'goals',     icon: 'target',       label: t.settingsGoals,     value: `${calorieTarget} ${t.cal}` },
    { key: 'diet',      icon: 'heart',        label: t.settingsDiet,      value: dietLabel },
    { key: 'allergens', icon: 'alert-circle', label: t.settingsAllergens, value: `${allergensCount} ${isAr ? 'مضبوطة' : 'set'}` },
  ];

  const interactiveRows = [
    {
      key: 'language',
      icon: 'globe',
      label: t.settingsLang,
      value: lang === 'ar' ? 'العربية' : 'English',
      onClick: () => setModal('language'),
    },
    {
      key: 'appearance',
      icon: 'moon',
      label: t.settingsAppearance,
      value: tweak.dark ? (isAr ? 'داكن' : 'Dark') : (isAr ? 'فاتح' : 'Light'),
      onClick: () => setTweak('dark', !tweak.dark),
    },
  ];

  const isPlusForSection = isPlus;

  const initials = (displayName || '?').slice(0, 1).toUpperCase();

  return (
    <div className="page">
      <div className="page-eyebrow">{isAr ? 'حسابي' : 'Profile'}</div>
      <h1 className="page-title">
        {displayName}
        <span style={{ display: 'block', color: 'var(--fg-muted)', fontSize: 18, fontWeight: 600, marginTop: 8 }}>
          {email}
          {isPlus ? <> · <span style={{ color: 'var(--accent)', fontWeight: 800 }}>{t.plusBadge}</span></> : null}
        </span>
      </h1>

      <div className="profile-grid" style={{ marginTop: 28 }}>
        <div className="profile-card">
          <div className="profile-avatar">
            {user && user.profileImageUri
              ? <img src={user.profileImageUri} alt="" style={{ width: '100%', height: '100%', borderRadius: '50%', objectFit: 'cover' }} />
              : initials
            }
          </div>
          <div style={{ fontWeight: 700, fontSize: 18, color: 'var(--fg)' }}>{displayName}</div>
          <div style={{ fontSize: 13, color: 'var(--fg-muted)', marginTop: 4 }}>{email}</div>
          <div className="stat-tiles">
            {stats.map(s => (
              <div key={s.l} className="stat-tile">
                <div className="stat-tile-value">{s.v}</div>
                <div className="stat-tile-label">{s.l}</div>
              </div>
            ))}
          </div>
          <button className="btn btn-soft" style={{ marginTop: 18, width: '100%' }} onClick={() => setModal('info')}>
            <Icon name="edit-2" size={14} /> {isAr ? 'تعديل الحساب' : 'Edit profile'}
          </button>
          <button className="btn btn-soft" style={{ marginTop: 8, width: '100%' }} onClick={onLogout}>
            <Icon name="log-out" size={14} /> {isAr ? 'تسجيل خروج' : 'Log out'}
          </button>
        </div>

        <div>
          <div className="profile-section-title">{isAr ? 'الإعدادات' : 'Settings'}</div>
          <div className="settings-list">
            {editableRows.map((s) => (
              <div className="settings-row" key={s.key} onClick={() => setModal(s.key)}>
                <div className="settings-row-icon"><Icon name={s.icon} size={18} /></div>
                <div className="settings-row-name">{s.label}</div>
                <div className="settings-row-value">{s.value}</div>
                <Icon name="chevron-right" size={18} color="var(--fg-muted)" />
              </div>
            ))}
            {interactiveRows.map((s) => (
              <div className="settings-row" key={s.key} onClick={s.onClick}>
                <div className="settings-row-icon"><Icon name={s.icon} size={18} /></div>
                <div className="settings-row-name">{s.label}</div>
                <div className="settings-row-value">{s.value}</div>
                <Icon name="chevron-right" size={18} color="var(--fg-muted)" />
              </div>
            ))}
          </div>

          <div className="profile-section-title">{isAr ? 'الاشتراك' : 'Subscription'}</div>
          <div className="settings-list">
            <div className="settings-row" style={{ cursor: 'default' }}>
              <div className="settings-row-icon"><Icon name="star" size={18} color={isPlusForSection ? 'var(--accent)' : 'var(--fg-muted)'} /></div>
              <div className="settings-row-name">
                {isPlusForSection
                  ? (isAr ? 'Saladizer Plus نشط' : 'Saladizer Plus active')
                  : (isAr ? 'الباقة المجانية' : 'Free plan')}
              </div>
              <div className="settings-row-value" style={{ fontSize: 12, textAlign: 'end', color: 'var(--fg-muted)' }}>
                {isPlusForSection
                  ? (isAr ? 'يدار من تطبيق الجوال' : 'Managed from the mobile app')
                  : (isAr ? 'فعّل من تطبيق الجوال' : 'Activate in the mobile app')}
              </div>
            </div>
          </div>

          <div className="profile-section-title">{isAr ? 'الأمان' : 'Security'}</div>
          <div className="settings-list">
            <div className="settings-row" onClick={() => setModal('password')}>
              <div className="settings-row-icon"><Icon name="lock" size={18} /></div>
              <div className="settings-row-name">{isAr ? 'تغيير كلمة المرور' : 'Change password'}</div>
              <Icon name="chevron-right" size={18} color="var(--fg-muted)" />
            </div>
            <div className="settings-row" onClick={() => setModal('delete')}>
              <div className="settings-row-icon" style={{ color: 'var(--danger)' }}><Icon name="trash-2" size={18} color="var(--danger)" /></div>
              <div className="settings-row-name" style={{ color: 'var(--danger)' }}>{isAr ? 'حذف الحساب' : 'Delete account'}</div>
              <Icon name="chevron-right" size={18} color="var(--fg-muted)" />
            </div>
          </div>

          {isAdmin ? (
            <>
              <div className="profile-section-title">{isAr ? 'المسؤول' : 'Admin'}</div>
              <div className="settings-list">
                <a className="settings-row" href="/saladctrlpnl" target="_blank" rel="noreferrer" style={{ textDecoration: 'none', color: 'inherit' }}>
                  <div className="settings-row-icon"><Icon name="shield" size={18} /></div>
                  <div className="settings-row-name">{isAr ? 'لوحة التحكم' : 'Admin panel'}</div>
                  <Icon name="external-link" size={18} color="var(--fg-muted)" />
                </a>
              </div>
            </>
          ) : null}
        </div>
      </div>

      {/* Modals */}
      <EditPersonalInfoModal
        open={modal === 'info'}
        onClose={() => setModal(null)}
        lang={lang}
        user={user}
        onSaved={onProfileSaved}
      />
      <EditGoalsModal
        open={modal === 'goals'}
        onClose={() => setModal(null)}
        lang={lang}
        profile={profile}
        onSaved={onProfileSaved}
      />
      <EditDietModal
        open={modal === 'diet'}
        onClose={() => setModal(null)}
        lang={lang}
        profile={profile}
        onSaved={onProfileSaved}
      />
      <EditAllergensModal
        open={modal === 'allergens'}
        onClose={() => setModal(null)}
        lang={lang}
        profile={profile}
        onSaved={onProfileSaved}
      />
      <EditLanguageModal
        open={modal === 'language'}
        onClose={() => setModal(null)}
        lang={lang}
        onChangeLang={(l) => { if (setLang) setLang(l); }}
      />
      <ChangePasswordModal
        open={modal === 'password'}
        onClose={() => setModal(null)}
        lang={lang}
        user={user}
      />
      <DeleteAccountModal
        open={modal === 'delete'}
        onClose={() => setModal(null)}
        lang={lang}
        user={user}
        onDeleted={onAccountDeleted}
      />
    </div>
  );
}

Object.assign(window, {
  DashboardView, BuilderView, ExploreView, SavedView, ProfileView,
  PresetCard, SavedCard, MacroBar, computeTotals,
});
