// Saladizer Web — Settings + Profile editor + Notifications drawer.
// Provides modal-based editors that reuse the existing API endpoints.

// ───────────────────────────────────────────────────────────
// Generic modal shell
// ───────────────────────────────────────────────────────────
function Modal({ open, onClose, title, children, footer, wide }) {
  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div
        className={'modal' + (wide ? ' modal-wide' : '')}
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-modal="true"
      >
        <div className="modal-head">
          <h3>{title}</h3>
          <button className="modal-close" onClick={onClose} aria-label="Close">
            <Icon name="x" size={18} />
          </button>
        </div>
        <div className="modal-body">{children}</div>
        {footer ? <div className="modal-foot">{footer}</div> : null}
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────
// Edit personal info (full name + image URL)
// ───────────────────────────────────────────────────────────
function EditPersonalInfoModal({ open, onClose, lang, user, onSaved }) {
  const isAr = lang === 'ar';
  const [fullName, setFullName] = React.useState('');
  const [imageUri, setImageUri] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const fileRef = React.useRef(null);

  React.useEffect(() => {
    if (open) {
      setFullName(user?.fullName || '');
      setImageUri(user?.profileImageUri || '');
      setErr('');
    }
  }, [open, user]);

  function onPickFile(e) {
    const file = e.target.files && e.target.files[0];
    e.target.value = '';
    if (!file) return;
    const okTypes = ['image/png', 'image/jpeg', 'image/webp'];
    if (!okTypes.includes(file.type)) {
      setErr(isAr ? 'الصيغة غير مدعومة (PNG / JPG / WebP فقط)' : 'Unsupported format (PNG / JPG / WebP only)');
      return;
    }
    if (file.size > 2 * 1024 * 1024) {
      setErr(isAr ? 'الملف أكبر من ٢ ميغابايت' : 'File is larger than 2 MB');
      return;
    }
    const reader = new FileReader();
    reader.onload = async () => {
      const dataUrl = String(reader.result || '');
      // Upload to the backend right away so the database only ever holds a
      // short URL — never the multi-MB base64 blob.
      setBusy(true);
      try {
        const out = await window.api.uploadProfileAvatar(dataUrl);
        if (out && out.url) {
          setImageUri(out.url);
          setErr('');
        } else {
          setErr(isAr ? 'تعذّر رفع الصورة' : 'Could not upload image');
        }
      } catch (uploadErr) {
        console.error('[Saladizer] uploadProfileAvatar failed:', uploadErr);
        setErr((uploadErr && uploadErr.data?.error) || (isAr ? 'تعذّر رفع الصورة' : 'Could not upload image'));
      } finally {
        setBusy(false);
      }
    };
    reader.onerror = () => {
      setErr(isAr ? 'تعذّر قراءة الملف' : 'Could not read file');
    };
    reader.readAsDataURL(file);
  }

  async function save() {
    setBusy(true);
    setErr('');
    try {
      const updated = await window.api.updateProfile({
        fullName: fullName.trim() || null,
        profileImageUri: imageUri.trim() || null,
      });
      onSaved && onSaved(updated);
      onClose();
    } catch (e) {
      console.error('[Saladizer] updateProfile failed:', e);
      setErr((e && e.data?.error) || (isAr ? 'تعذّر الحفظ' : 'Could not save'));
    } finally {
      setBusy(false);
    }
  }

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={isAr ? 'تعديل المعلومات الشخصية' : 'Edit personal info'}
      footer={
        <>
          <button className="btn btn-soft" onClick={onClose}>
            {isAr ? 'إلغاء' : 'Cancel'}
          </button>
          <button className="btn btn-primary" disabled={busy} onClick={save}>
            {busy ? (isAr ? 'جارٍ الحفظ...' : 'Saving...') : (isAr ? 'حفظ' : 'Save')}
          </button>
        </>
      }
    >
      <label className="form-field">
        <span>{isAr ? 'الاسم الكامل' : 'Full name'}</span>
        <input
          type="text"
          value={fullName}
          onChange={(e) => setFullName(e.target.value)}
          placeholder={isAr ? 'اسمك' : 'Your name'}
        />
      </label>
      <label className="form-field">
        <span>{isAr ? 'رابط الصورة الشخصية' : 'Profile image URL'}</span>
        <div style={{ display: 'flex', gap: 8, alignItems: 'stretch' }}>
          <input
            type="url"
            value={imageUri.startsWith('data:') ? '' : imageUri}
            onChange={(e) => setImageUri(e.target.value)}
            placeholder={imageUri.startsWith('data:') ? (isAr ? '(صورة مرفوعة)' : '(uploaded image)') : 'https://...'}
            style={{ flex: 1 }}
          />
          <button
            type="button"
            className="btn btn-soft btn-sm"
            onClick={() => fileRef.current && fileRef.current.click()}
            style={{ whiteSpace: 'nowrap' }}
          >
            <Icon name="upload" size={13} /> {isAr ? 'رفع من الكمبيوتر' : 'Upload from computer'}
          </button>
          <input
            ref={fileRef}
            type="file"
            accept="image/png,image/jpeg,image/webp"
            onChange={onPickFile}
            style={{ display: 'none' }}
          />
        </div>
        {imageUri ? (
          <img
            src={imageUri}
            alt=""
            style={{ width: 64, height: 64, borderRadius: '50%', marginTop: 10, objectFit: 'cover' }}
            onError={(e) => { e.currentTarget.style.display = 'none'; }}
          />
        ) : null}
      </label>
      {err ? <div className="auth-error">{err}</div> : null}
    </Modal>
  );
}

// ───────────────────────────────────────────────────────────
// Edit nutrition goals
// ───────────────────────────────────────────────────────────
function EditGoalsModal({ open, onClose, lang, profile, onSaved }) {
  const isAr = lang === 'ar';
  const [calories, setCalories] = React.useState(2000);
  const [protein, setProtein] = React.useState(25);
  const [carbs, setCarbs] = React.useState(50);
  const [fat, setFat] = React.useState(25);
  const [goalType, setGoalType] = React.useState('balanced');
  const [gender, setGender] = React.useState('male');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  React.useEffect(() => {
    if (open && profile) {
      setCalories(profile.dailyCalorieTarget ?? 2000);
      setProtein(profile.proteinPercentage ?? 25);
      setCarbs(profile.carbsPercentage ?? 50);
      setFat(profile.fatPercentage ?? 25);
      setGoalType(profile.nutritionGoalType || 'balanced');
      setGender(profile.gender || 'male');
      setErr('');
    }
  }, [open, profile]);

  const total = Number(protein) + Number(carbs) + Number(fat);
  const totalOk = Math.abs(total - 100) <= 1;

  async function save() {
    if (!totalOk) {
      setErr(isAr ? 'مجموع النِسب لازم يساوي 100%' : 'Macro percentages must add up to 100%');
      return;
    }
    setBusy(true);
    setErr('');
    try {
      const updated = await window.api.updateProfile({
        dailyCalorieTarget: Number(calories),
        proteinPercentage: Number(protein),
        carbsPercentage: Number(carbs),
        fatPercentage: Number(fat),
        nutritionGoalType: goalType,
        gender,
      });
      onSaved && onSaved(updated);
      onClose();
    } catch (e) {
      console.error('[Saladizer] updateProfile (goals) failed:', e);
      setErr((e && e.data?.error) || (isAr ? 'تعذّر الحفظ' : 'Could not save'));
    } finally {
      setBusy(false);
    }
  }

  const goalOptions = isAr
    ? [
        ['balanced', 'متوازن'],
        ['weight_loss', 'خسارة وزن'],
        ['muscle_gain', 'بناء عضلات'],
        ['high_protein', 'بروتين عالٍ'],
        ['low_carb', 'كربوهيدرات منخفضة'],
      ]
    : [
        ['balanced', 'Balanced'],
        ['weight_loss', 'Weight loss'],
        ['muscle_gain', 'Muscle gain'],
        ['high_protein', 'High protein'],
        ['low_carb', 'Low carb'],
      ];

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={isAr ? 'الأهداف الغذائية' : 'Nutrition goals'}
      footer={
        <>
          <button className="btn btn-soft" onClick={onClose}>
            {isAr ? 'إلغاء' : 'Cancel'}
          </button>
          <button className="btn btn-primary" disabled={busy} onClick={save}>
            {busy ? (isAr ? 'جارٍ الحفظ...' : 'Saving...') : (isAr ? 'حفظ' : 'Save')}
          </button>
        </>
      }
    >
      <label className="form-field">
        <span>{isAr ? 'السعرات اليومية' : 'Daily calories'}</span>
        <input
          type="number"
          min={1000}
          max={5000}
          step={50}
          value={calories}
          onChange={(e) => setCalories(e.target.value)}
        />
      </label>

      <label className="form-field">
        <span>{isAr ? 'نوع الهدف' : 'Goal type'}</span>
        <select value={goalType} onChange={(e) => setGoalType(e.target.value)}>
          {goalOptions.map(([v, l]) => (
            <option key={v} value={v}>{l}</option>
          ))}
        </select>
      </label>

      <label className="form-field">
        <span>{isAr ? 'الجنس' : 'Gender'}</span>
        <select value={gender} onChange={(e) => setGender(e.target.value)}>
          <option value="male">{isAr ? 'ذكر' : 'Male'}</option>
          <option value="female">{isAr ? 'أنثى' : 'Female'}</option>
        </select>
      </label>

      <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.08em', marginTop: 14, marginBottom: 8 }}>
        {isAr ? 'نسب المكرونيوترينت' : 'Macro split'}
      </div>

      <div className="form-row-3">
        <label className="form-field">
          <span>{isAr ? 'بروتين %' : 'Protein %'}</span>
          <input type="number" min={0} max={100} value={protein} onChange={(e) => setProtein(e.target.value)} />
        </label>
        <label className="form-field">
          <span>{isAr ? 'كربوهيدرات %' : 'Carbs %'}</span>
          <input type="number" min={0} max={100} value={carbs} onChange={(e) => setCarbs(e.target.value)} />
        </label>
        <label className="form-field">
          <span>{isAr ? 'دهون %' : 'Fat %'}</span>
          <input type="number" min={0} max={100} value={fat} onChange={(e) => setFat(e.target.value)} />
        </label>
      </div>

      <div style={{ fontSize: 13, color: totalOk ? 'var(--primary)' : 'var(--danger)', fontWeight: 700, marginTop: 6 }}>
        {isAr ? 'المجموع' : 'Total'}: {total}% {totalOk ? '✓' : '✗'}
      </div>

      {err ? <div className="auth-error">{err}</div> : null}
    </Modal>
  );
}

// ───────────────────────────────────────────────────────────
// Edit diet flags
// ───────────────────────────────────────────────────────────
function EditDietModal({ open, onClose, lang, profile, onSaved }) {
  const isAr = lang === 'ar';
  const [flags, setFlags] = React.useState({
    isVegetarian: false, isKeto: false, isLowSodium: false, noAddedSugar: false,
  });
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  React.useEffect(() => {
    if (open && profile) {
      setFlags({
        isVegetarian: !!profile.isVegetarian,
        isKeto: !!profile.isKeto,
        isLowSodium: !!profile.isLowSodium,
        noAddedSugar: !!profile.noAddedSugar,
      });
      setErr('');
    }
  }, [open, profile]);

  async function save() {
    setBusy(true);
    setErr('');
    try {
      const updated = await window.api.updateProfile(flags);
      onSaved && onSaved(updated);
      onClose();
    } catch (e) {
      console.error('[Saladizer] updateProfile (diet) failed:', e);
      setErr((e && e.data?.error) || (isAr ? 'تعذّر الحفظ' : 'Could not save'));
    } finally {
      setBusy(false);
    }
  }

  const items = isAr
    ? [
        ['isVegetarian', 'نباتي'],
        ['isKeto', 'كيتو'],
        ['isLowSodium', 'صوديوم منخفض'],
        ['noAddedSugar', 'بدون سكر مضاف'],
      ]
    : [
        ['isVegetarian', 'Vegetarian'],
        ['isKeto', 'Keto'],
        ['isLowSodium', 'Low sodium'],
        ['noAddedSugar', 'No added sugar'],
      ];

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={isAr ? 'تفضيلات النظام الغذائي' : 'Diet preferences'}
      footer={
        <>
          <button className="btn btn-soft" onClick={onClose}>
            {isAr ? 'إلغاء' : 'Cancel'}
          </button>
          <button className="btn btn-primary" disabled={busy} onClick={save}>
            {busy ? (isAr ? 'جارٍ الحفظ...' : 'Saving...') : (isAr ? 'حفظ' : 'Save')}
          </button>
        </>
      }
    >
      {items.map(([k, l]) => (
        <label key={k} className="toggle-row">
          <span>{l}</span>
          <input
            type="checkbox"
            checked={!!flags[k]}
            onChange={(e) => setFlags(f => ({ ...f, [k]: e.target.checked }))}
          />
        </label>
      ))}
      {err ? <div className="auth-error">{err}</div> : null}
    </Modal>
  );
}

// ───────────────────────────────────────────────────────────
// Edit allergens & disliked ingredients (tag input)
// ───────────────────────────────────────────────────────────
function TagList({ value, onChange, placeholder, lang }) {
  const [draft, setDraft] = React.useState('');
  const tags = Array.isArray(value) ? value : [];
  function add(t) {
    const trimmed = (t || draft).trim();
    if (!trimmed) return;
    if (tags.includes(trimmed)) { setDraft(''); return; }
    onChange([...tags, trimmed]);
    setDraft('');
  }
  function remove(t) {
    onChange(tags.filter(x => x !== t));
  }
  return (
    <div className="tag-input">
      <div className="tag-list">
        {tags.map(t => (
          <span key={t} className="tag-chip">
            {t}
            <button type="button" onClick={() => remove(t)} aria-label={lang === 'ar' ? 'إزالة' : 'Remove'}>
              <Icon name="x" size={11} />
            </button>
          </span>
        ))}
      </div>
      <div className="tag-add">
        <input
          type="text"
          value={draft}
          onChange={(e) => setDraft(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === 'Enter' || e.key === ',') { e.preventDefault(); add(); }
          }}
          placeholder={placeholder}
        />
        <button type="button" className="btn btn-soft btn-sm" onClick={() => add()}>
          <Icon name="plus" size={12} /> {lang === 'ar' ? 'إضافة' : 'Add'}
        </button>
      </div>
    </div>
  );
}

const ALLERGEN_CHOICES = [
  { id: 'tree_nuts',    en: 'Tree nuts',     ar: 'مكسرات شجرية' },
  { id: 'peanuts',      en: 'Peanuts',       ar: 'فول سوداني' },
  { id: 'milk',         en: 'Milk',          ar: 'حليب' },
  { id: 'eggs',         en: 'Eggs',          ar: 'بيض' },
  { id: 'sesame',       en: 'Sesame',        ar: 'سمسم' },
  { id: 'gluten_wheat', en: 'Gluten / Wheat', ar: 'جلوتين/قمح' },
  { id: 'soy',          en: 'Soy',           ar: 'فول الصويا' },
  { id: 'fish',         en: 'Fish',          ar: 'سمك' },
  { id: 'crustaceans',  en: 'Crustaceans',   ar: 'قشريات' },
  { id: 'mustard',      en: 'Mustard',       ar: 'خردل' },
  { id: 'celery',       en: 'Celery',        ar: 'كرفس' },
  { id: 'sulphites',    en: 'Sulphites',     ar: 'كبريتيت' },
];

const ALLERGEN_ID_MIGRATION = {
  nuts: 'tree_nuts',
  dairy: 'milk',
  shellfish: 'crustaceans',
  gluten: 'gluten_wheat',
  sulfites: 'sulphites',
};

function migrateAllergenIds(list) {
  if (!Array.isArray(list)) return [];
  const valid = new Set(ALLERGEN_CHOICES.map(c => c.id));
  const out = [];
  for (const raw of list) {
    const mapped = ALLERGEN_ID_MIGRATION[raw] || raw;
    if (valid.has(mapped) && !out.includes(mapped)) out.push(mapped);
  }
  return out;
}

function ChipPicker({ options, selected, onToggle, lang }) {
  const isAr = lang === 'ar';
  return (
    <div className="chip-picker" style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
      {options.map(opt => {
        const on = selected.includes(opt.id);
        return (
          <button
            key={opt.id}
            type="button"
            onClick={() => onToggle(opt.id)}
            className={'chip' + (on ? ' on' : '')}
            style={{
              padding: '6px 12px',
              borderRadius: 999,
              border: '1px solid ' + (on ? 'var(--primary)' : 'var(--border)'),
              background: on ? 'var(--primary-soft)' : 'var(--bg-surface)',
              color: on ? 'var(--primary)' : 'var(--fg)',
              fontSize: 13,
              fontWeight: 600,
              cursor: 'pointer',
              display: 'inline-flex', alignItems: 'center', gap: 6,
            }}
          >
            {on ? <Icon name="check" size={11} color="var(--primary)" /> : null}
            {isAr ? opt.ar : opt.en}
          </button>
        );
      })}
    </div>
  );
}

function EditAllergensModal({ open, onClose, lang, profile, onSaved }) {
  const isAr = lang === 'ar';
  const [allergens, setAllergens] = React.useState([]);
  const [dislikes, setDislikes] = React.useState([]);
  const [search, setSearch] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  // Cache of server-side ingredient metadata keyed by English name, so
  // dislike chips can render their Arabic label + glyph for items that
  // aren't in the local 25-item mock catalog.
  const [extraMeta, setExtraMeta] = React.useState({});

  React.useEffect(() => {
    if (open && profile) {
      setAllergens(migrateAllergenIds(profile.allergens));
      setDislikes(Array.isArray(profile.dislikedIngredients) ? profile.dislikedIngredients : []);
      setSearch('');
      setErr('');
    }
  }, [open, profile]);

  function toggleAllergen(id) {
    setAllergens(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]);
  }
  function toggleDislike(name) {
    setDislikes(prev => prev.includes(name) ? prev.filter(x => x !== name) : [...prev, name]);
  }

  const allIngs = (window.ALL_INGREDIENTS || []);
  const qRaw = search.trim();
  const q = qRaw.toLowerCase();
  // Server-backed search across the full catalog (USDA + chef).
  const serverSearch = window.useDebouncedIngredientSearch
    ? window.useDebouncedIngredientSearch(search, { minChars: 2, debounceMs: 250, limit: 20 })
    : { items: [], loading: false, error: null };
  let matchIngs;
  if (q.length >= 2) {
    matchIngs = serverSearch.items
      .filter(i => !dislikes.includes(i.name))
      .slice(0, 12);
  } else if (q.length === 1) {
    matchIngs = allIngs
      .filter(i => !dislikes.includes(i.name))
      .filter(i => (i.name || '').toLowerCase().includes(q) || (i.ar || '').includes(qRaw))
      .slice(0, 8);
  } else {
    matchIngs = [];
  }

  function addDislike(ing) {
    const name = typeof ing === 'string' ? ing : (ing && ing.name) || '';
    if (!name) return;
    if (ing && typeof ing === 'object' && !allIngs.find(i => i.name === name)) {
      // Server-only ingredient: remember its display metadata for chips.
      setExtraMeta(prev => prev[name] ? prev : { ...prev, [name]: { name, ar: ing.ar, glyph: ing.glyph } });
    }
    setDislikes(prev => prev.includes(name) ? prev : [...prev, name]);
    setSearch('');
  }
  function removeDislike(name) {
    setDislikes(prev => prev.filter(x => x !== name));
  }
  function findIng(name) {
    return allIngs.find(i => i.name === name) || extraMeta[name] || null;
  }

  async function save() {
    setBusy(true);
    setErr('');
    try {
      const updated = await window.api.updateProfile({
        allergens,
        dislikedIngredients: dislikes,
      });
      onSaved && onSaved(updated);
      onClose();
    } catch (e) {
      console.error('[Saladizer] updateProfile (allergens) failed:', e);
      setErr((e && e.data?.error) || (isAr ? 'تعذّر الحفظ' : 'Could not save'));
    } finally {
      setBusy(false);
    }
  }

  return (
    <Modal
      open={open}
      onClose={onClose}
      wide
      title={isAr ? 'الحساسية والمكونات غير المحبوبة' : 'Allergens & dislikes'}
      footer={
        <>
          <button className="btn btn-soft" onClick={onClose}>
            {isAr ? 'إلغاء' : 'Cancel'}
          </button>
          <button className="btn btn-primary" disabled={busy} onClick={save}>
            {busy ? (isAr ? 'جارٍ الحفظ...' : 'Saving...') : (isAr ? 'حفظ' : 'Save')}
          </button>
        </>
      }
    >
      <div className="form-field">
        <span style={{ fontWeight: 700 }}>{isAr ? 'الحساسية' : 'Allergens'}</span>
        <div style={{ fontSize: 12, color: 'var(--fg-muted)', margin: '4px 0 10px' }}>
          {isAr ? 'اختر ما يخصّك من القائمة:' : 'Tap the items that apply to you:'}
        </div>
        <ChipPicker
          options={ALLERGEN_CHOICES}
          selected={allergens}
          onToggle={toggleAllergen}
          lang={lang}
        />
      </div>

      <div className="form-field" style={{ marginTop: 18 }}>
        <span style={{ fontWeight: 700 }}>{isAr ? 'مكونات لا تحبها' : 'Disliked ingredients'}</span>
        <div style={{ fontSize: 12, color: 'var(--fg-muted)', margin: '4px 0 8px' }}>
          {isAr
            ? 'ابحث وأضف ما لا تحبه. سيتفاداها الشيف.'
            : 'Search and add what you dislike. Chef Saladizer will avoid them.'}
        </div>

        {dislikes.length > 0 ? (
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 10 }}>
            {dislikes.map(name => {
              const ing = findIng(name);
              return (
                <span
                  key={name}
                  className="chip on"
                  style={{
                    padding: '6px 10px', borderRadius: 999,
                    border: '1px solid var(--danger)',
                    background: 'rgba(244,67,54,0.10)',
                    color: 'var(--danger)',
                    fontSize: 12, fontWeight: 600,
                    display: 'inline-flex', alignItems: 'center', gap: 6,
                  }}
                >
                  {ing ? <span>{ing.glyph}</span> : null}
                  <span>{ing ? (isAr ? ing.ar : ing.name) : name}</span>
                  <button
                    type="button"
                    onClick={() => removeDislike(name)}
                    aria-label={isAr ? 'إزالة' : 'Remove'}
                    style={{
                      background: 'transparent', border: 0, padding: 0, marginInlineStart: 2,
                      color: 'var(--danger)', cursor: 'pointer', display: 'inline-flex',
                    }}
                  >
                    <Icon name="x" size={11} />
                  </button>
                </span>
              );
            })}
          </div>
        ) : null}

        <div style={{ position: 'relative' }}>
          <input
            type="text"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder={isAr ? 'ابحث عن مكون لإضافته...' : 'Search ingredients to add...'}
            style={{
              width: '100%', padding: '8px 12px', borderRadius: 10,
              border: '1px solid var(--border)', background: 'var(--bg-surface)',
              color: 'var(--fg)', fontSize: 14,
            }}
          />
          {qRaw ? (
            <div style={{
              marginTop: 6,
              border: '1px solid var(--border)',
              borderRadius: 12,
              background: 'var(--bg-surface)',
              boxShadow: 'var(--shadow-card)',
              overflow: 'hidden',
              maxHeight: 280,
              overflowY: 'auto',
            }}>
              {matchIngs.length === 0 && q.length >= 2 && serverSearch.loading ? (
                <div style={{ fontSize: 13, color: 'var(--fg-muted)', padding: 12, textAlign: 'center' }}>
                  {isAr ? 'جارٍ البحث…' : 'Searching…'}
                </div>
              ) : matchIngs.length === 0 && q.length >= 2 && serverSearch.error ? (
                <div style={{ fontSize: 13, color: 'var(--danger)', padding: 12, textAlign: 'center' }}>
                  {isAr ? 'تعذّر البحث' : 'Search failed'}
                </div>
              ) : matchIngs.length === 0 ? (
                <div style={{ fontSize: 13, color: 'var(--fg-muted)', padding: 12, textAlign: 'center' }}>
                  {isAr ? 'لا توجد نتائج' : 'No matches'}
                </div>
              ) : matchIngs.map(ing => (
                <button
                  key={ing.id}
                  type="button"
                  onClick={() => addDislike(ing)}
                  style={{
                    display: 'flex', alignItems: 'center', gap: 10,
                    width: '100%', textAlign: isAr ? 'right' : 'left',
                    padding: '8px 12px', background: 'transparent',
                    border: 0, borderBottom: '1px solid var(--border)',
                    color: 'var(--fg)', fontSize: 13, fontFamily: 'inherit',
                    cursor: 'pointer',
                  }}
                  onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--bg-tinted)'; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}
                >
                  <span style={{ fontSize: 18 }}>{ing.glyph}</span>
                  <span style={{ flex: 1 }}>{isAr ? ing.ar : ing.name}</span>
                  <Icon name="plus" size={13} color="var(--primary)" />
                </button>
              ))}
            </div>
          ) : null}
        </div>
      </div>
      {err ? <div className="auth-error" style={{ marginTop: 12 }}>{err}</div> : null}
    </Modal>
  );
}

// ───────────────────────────────────────────────────────────
// Edit language (chip picker)
// ───────────────────────────────────────────────────────────
function EditLanguageModal({ open, onClose, lang, onChangeLang }) {
  const isAr = lang === 'ar';
  const [pick, setPick] = React.useState(lang || 'en');

  React.useEffect(() => { if (open) setPick(lang || 'en'); }, [open, lang]);

  function save() {
    if (pick !== lang && onChangeLang) onChangeLang(pick);
    onClose();
  }

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={isAr ? 'اللغة' : 'Language'}
      footer={
        <>
          <button className="btn btn-soft" onClick={onClose}>
            {isAr ? 'إلغاء' : 'Cancel'}
          </button>
          <button className="btn btn-primary" onClick={save}>
            {isAr ? 'حفظ' : 'Save'}
          </button>
        </>
      }
    >
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {[
          { id: 'en', label: 'English' },
          { id: 'ar', label: 'العربية' },
        ].map(opt => {
          const on = pick === opt.id;
          return (
            <button
              key={opt.id}
              type="button"
              onClick={() => setPick(opt.id)}
              style={{
                padding: '12px 14px', borderRadius: 12,
                border: '1px solid ' + (on ? 'var(--primary)' : 'var(--border)'),
                background: on ? 'var(--primary-soft)' : 'var(--bg-surface)',
                color: on ? 'var(--primary)' : 'var(--fg)',
                fontSize: 15, fontWeight: 700, textAlign: 'start',
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                cursor: 'pointer',
              }}
            >
              <span>{opt.label}</span>
              {on ? <Icon name="check" size={16} color="var(--primary)" /> : null}
            </button>
          );
        })}
      </div>
    </Modal>
  );
}

// ───────────────────────────────────────────────────────────
// Change password
// ───────────────────────────────────────────────────────────
function ChangePasswordModal({ open, onClose, lang, user }) {
  const isAr = lang === 'ar';
  const [current, setCurrent] = React.useState('');
  const [next, setNext] = React.useState('');
  const [confirm, setConfirm] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const [done, setDone] = React.useState(false);

  React.useEffect(() => {
    if (open) {
      setCurrent(''); setNext(''); setConfirm(''); setErr(''); setDone(false);
    }
  }, [open]);

  async function save() {
    if (next.length < 6) {
      setErr(isAr ? 'كلمة المرور لازم تكون 6 أحرف على الأقل' : 'Password must be at least 6 characters');
      return;
    }
    if (next !== confirm) {
      setErr(isAr ? 'تأكيد كلمة المرور لا يطابق' : 'Password confirmation does not match');
      return;
    }
    setBusy(true);
    setErr('');
    try {
      await window.api.changePassword(current, next);
      setDone(true);
      setTimeout(onClose, 1200);
    } catch (e) {
      console.error('[Saladizer] changePassword failed:', e);
      setErr((e && e.data?.error) || (isAr ? 'تعذّر تغيير كلمة المرور' : 'Could not change password'));
    } finally {
      setBusy(false);
    }
  }

  const provider = user?.provider;
  const isEmailProvider = !provider || provider === 'email';

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={isAr ? 'تغيير كلمة المرور' : 'Change password'}
      footer={
        <>
          <button className="btn btn-soft" onClick={onClose}>
            {isAr ? 'إغلاق' : 'Close'}
          </button>
          {!done && (
            <button className="btn btn-primary" disabled={busy} onClick={save}>
              {busy ? (isAr ? 'جارٍ...' : 'Working...') : (isAr ? 'تغيير' : 'Update')}
            </button>
          )}
        </>
      }
    >
      {done ? (
        <div style={{ padding: '8px 0', color: 'var(--primary)', fontWeight: 700 }}>
          {isAr ? 'تم تغيير كلمة المرور بنجاح ✓' : 'Password changed successfully ✓'}
        </div>
      ) : (
        <>
          {isEmailProvider ? (
            <label className="form-field">
              <span>{isAr ? 'كلمة المرور الحالية' : 'Current password'}</span>
              <input type="password" autoComplete="current-password" value={current} onChange={(e) => setCurrent(e.target.value)} />
            </label>
          ) : (
            <div className="info-note">
              {isAr ? 'حسابك يستخدم تسجيل دخول اجتماعي. الآن تقدر تضع كلمة مرور.' : 'Your account uses social sign-in. You can now set a password.'}
            </div>
          )}
          <label className="form-field">
            <span>{isAr ? 'كلمة المرور الجديدة' : 'New password'}</span>
            <input type="password" autoComplete="new-password" value={next} onChange={(e) => setNext(e.target.value)} minLength={6} />
          </label>
          <label className="form-field">
            <span>{isAr ? 'تأكيد كلمة المرور' : 'Confirm password'}</span>
            <input type="password" autoComplete="new-password" value={confirm} onChange={(e) => setConfirm(e.target.value)} minLength={6} />
          </label>
          {err ? <div className="auth-error">{err}</div> : null}
        </>
      )}
    </Modal>
  );
}

// ───────────────────────────────────────────────────────────
// Delete account
// ───────────────────────────────────────────────────────────
function DeleteAccountModal({ open, onClose, lang, user, onDeleted }) {
  const isAr = lang === 'ar';
  const [confirmText, setConfirmText] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const expected = (user?.email || '').trim();
  const canDelete = confirmText.trim().toLowerCase() === expected.toLowerCase() && expected;

  React.useEffect(() => {
    if (open) { setConfirmText(''); setErr(''); }
  }, [open]);

  async function doDelete() {
    if (!canDelete) return;
    setBusy(true);
    setErr('');
    try {
      await window.api.deleteAccount();
      window.api.clearToken();
      onDeleted && onDeleted();
    } catch (e) {
      console.error('[Saladizer] deleteAccount failed:', e);
      setErr((e && e.data?.error) || (isAr ? 'تعذّر حذف الحساب' : 'Could not delete account'));
      setBusy(false);
    }
  }

  return (
    <Modal
      open={open}
      onClose={busy ? undefined : onClose}
      title={isAr ? 'حذف الحساب نهائياً' : 'Delete account permanently'}
      footer={
        <>
          <button className="btn btn-soft" onClick={onClose} disabled={busy}>
            {isAr ? 'إلغاء' : 'Cancel'}
          </button>
          <button className="btn btn-danger" disabled={!canDelete || busy} onClick={doDelete}>
            {busy ? (isAr ? 'جارٍ الحذف...' : 'Deleting...') : (isAr ? 'حذف نهائياً' : 'Delete forever')}
          </button>
        </>
      }
    >
      <div className="warn-box">
        {isAr
          ? 'هذا الإجراء لا يمكن التراجع عنه. سيتم حذف حسابك وكل سلطاتك المحفوظة وإعداداتك.'
          : 'This cannot be undone. Your account, saved salads, and settings will be removed.'}
      </div>
      <label className="form-field">
        <span>
          {isAr
            ? <>اكتب إيميلك <strong>{expected}</strong> للتأكيد</>
            : <>Type your email <strong>{expected}</strong> to confirm</>}
        </span>
        <input
          type="text"
          value={confirmText}
          onChange={(e) => setConfirmText(e.target.value)}
          placeholder={expected}
        />
      </label>
      {err ? <div className="auth-error">{err}</div> : null}
    </Modal>
  );
}

// ───────────────────────────────────────────────────────────
// Notifications drawer
// ───────────────────────────────────────────────────────────
function NotificationsDrawer({ open, onClose, lang }) {
  const isAr = lang === 'ar';
  const [items, setItems] = React.useState([]);
  const [loading, setLoading] = React.useState(false);

  React.useEffect(() => {
    if (!open) return;
    let cancelled = false;
    setLoading(true);
    (async () => {
      try {
        const out = await window.api.listNotifications();
        if (!cancelled) {
          const list = (out && Array.isArray(out.items)) ? out.items : (Array.isArray(out) ? out : []);
          setItems(list);
        }
        try { await window.api.markAllNotificationsRead(); } catch (_) {}
      } catch (e) {
        console.warn('[Saladizer] listNotifications failed:', e);
        if (!cancelled) setItems([]);
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, [open]);

  return (
    <>
      <div className={'chef-backdrop' + (open ? ' open' : '')} onClick={onClose} />
      <aside className={'notif-drawer' + (open ? ' open' : '')} aria-hidden={!open}>
        <div className="chef-head">
          <div>
            <div className="chef-name">{isAr ? 'الإشعارات' : 'Notifications'}</div>
            <div className="chef-sub">{items.length} {isAr ? 'إشعار' : 'updates'}</div>
          </div>
          <button className="chef-close" onClick={onClose}>
            <Icon name="x" size={18} />
          </button>
        </div>
        <div className="chef-body">
          {loading ? (
            <div className="view-loading">{isAr ? 'جارٍ التحميل...' : 'Loading...'}</div>
          ) : items.length === 0 ? (
            <div className="view-loading">{isAr ? 'ما عندك إشعارات بعد.' : 'No notifications yet.'}</div>
          ) : (
            items.map((n) => (
              <div key={n.id} className="notif-item">
                <div className="notif-title">{isAr ? (n.titleAr || n.titleEn) : (n.titleEn || n.titleAr)}</div>
                {n.bodyEn || n.bodyAr ? (
                  <div className="notif-body">{isAr ? (n.bodyAr || n.bodyEn) : (n.bodyEn || n.bodyAr)}</div>
                ) : null}
                <div className="notif-time">{n.createdAt ? new Date(n.createdAt).toLocaleString(isAr ? 'ar-SA' : 'en-US') : ''}</div>
              </div>
            ))
          )}
        </div>
      </aside>
    </>
  );
}

// Expose
Object.assign(window, {
  Modal,
  EditPersonalInfoModal, EditGoalsModal, EditDietModal, EditAllergensModal,
  EditLanguageModal,
  ChangePasswordModal, DeleteAccountModal,
  NotificationsDrawer,
});
