// Saladizer Web — main app.

function App() {
  // ── Tweakable defaults ─────────────────────────────────────
  const defaults = /*EDITMODE-BEGIN*/{
    "lang": "en",
    "dark": false,
    "palette": "app",
    "density": "comfortable"
  }/*EDITMODE-END*/;

  const [tweak, setTweak] = useTweaks(defaults);
  const lang = tweak.lang === 'ar' ? 'ar' : 'en';
  const t = useT(lang);
  const isAr = lang === 'ar';

  // ── Auth state ────────────────────────────────────────────
  const [authState, setAuthState] = React.useState('loading'); // 'loading' | 'guest' | 'authed'
  const [user, setUser] = React.useState(null);

  // ── App state ────────────────────────────────────────────
  const [view, setView] = React.useState('home');
  const [selections, setSelections] = React.useState({});
  const [saladName, setSaladName] = React.useState('');
  // Session-level cache of ingredients fetched from the backend that aren't
  // in the local 25-item mock catalog (USDA + chef-only items). Shared so the
  // Chef view can hand off chef-generated ingredients to the Builder.
  const [extraCatalog, setExtraCatalog] = React.useState({});
  const [savedSalads, setSavedSalads] = React.useState([]);
  const [savedLoading, setSavedLoading] = React.useState(false);
  const [chefOpen, setChefOpen] = React.useState(false);
  const [toast, setToast] = React.useState({ show: false, text: '' });
  // Set when the builder is opened directly from Chef Makes Me a Salad.
  // Passed to BuilderView to hide the ingredient grid and show the chef note.
  const [fromChef, setFromChef] = React.useState(false);
  const [chefNote, setChefNote] = React.useState(null); // { en: string[], ar: string[] }
  // The chef AI computes its own estimatedNutrition using its own ingredient
  // database, which won't match our USDA-per-100g math. To avoid showing two
  // different numbers for the same salad, we surface the chef's own estimate
  // in the builder until the user changes the ingredient list.
  const [chefNutrition, setChefNutrition] = React.useState(null); // { calories, protein, carbs, fat }
  // ── Apply theme + dir to <html> ───────────────────────────
  React.useEffect(() => {
    const html = document.documentElement;
    html.setAttribute('lang', lang);
    html.setAttribute('dir', isAr ? 'rtl' : 'ltr');
    html.setAttribute('data-theme', tweak.dark ? 'dark' : 'light');
    html.setAttribute('data-palette', tweak.palette === 'marketing' ? 'marketing' : 'app');
  }, [lang, isAr, tweak.dark, tweak.palette]);

  // ── Persist theme to backend for logged-in users ──
  // The backend settings schema only accepts `theme` ('system'|'light'|'dark');
  // language is part of the user profile and is updated by the language modal.
  const lastSyncedTheme = React.useRef('');
  React.useEffect(() => {
    if (authState !== 'authed') return;
    const next = tweak.dark ? 'dark' : 'light';
    if (lastSyncedTheme.current === next) return;
    lastSyncedTheme.current = next;
    const id = setTimeout(() => {
      window.api.updateSettings({ theme: next })
        .catch((e) => console.warn('[Saladizer] updateSettings failed:', e && (e.status || e.message)));
    }, 600);
    return () => clearTimeout(id);
  }, [authState, tweak.dark]);

  // ── Hydrate theme from backend once on login ──
  React.useEffect(() => {
    if (authState !== 'authed') return;
    let cancelled = false;
    (async () => {
      try {
        const s = await window.api.getSettings();
        if (cancelled || !s) return;
        if (s.theme === 'dark' && !tweak.dark) setTweak('dark', true);
        else if (s.theme === 'light' && tweak.dark) setTweak('dark', false);
      } catch (_) {}
    })();
    return () => { cancelled = true; };
  }, [authState]);

  // ── Load current user on mount ────────────────────────────
  React.useEffect(() => {
    let cancelled = false;
    async function init() {
      if (!window.api.getToken()) {
        if (!cancelled) setAuthState('guest');
        return;
      }
      try {
        const u = await window.api.me();
        if (!cancelled) {
          setUser(u);
          setAuthState('authed');
        }
      } catch (_) {
        if (!cancelled) setAuthState('guest');
      }
    }
    init();
    return () => { cancelled = true; };
  }, []);

  // ── Load user's saved salads once authed ──────────────────
  const reloadSaved = React.useCallback(async () => {
    if (authState !== 'authed') return;
    setSavedLoading(true);
    try {
      const list = await window.api.listSalads();
      setSavedSalads(Array.isArray(list) ? list : []);
    } catch (e) {
      console.error('[Saladizer] listSalads failed:', e && (e.status || e.message), e);
      setSavedSalads([]);
    } finally {
      setSavedLoading(false);
    }
  }, [authState]);

  React.useEffect(() => {
    if (authState === 'authed') reloadSaved();
  }, [authState, reloadSaved]);

  const showToast = (text) => {
    setToast({ show: true, text });
    setTimeout(() => setToast({ show: false, text: '' }), 2200);
  };

  // ── Save the current bowl as a salad on the backend ───────
  // BuilderView passes its resolved items + totals (which include any
  // server-fetched ingredients in `extraCatalog`). Fall back to the local
  // catalog when called without args so other callers keep working.
  const handleSave = async (resolvedItems, resolvedTotals) => {
    const items = Array.isArray(resolvedItems) && resolvedItems.length > 0
      ? resolvedItems.map(({ ing, qty }) => ({ id: ing.id, qty, ing }))
      : Object.entries(selections)
          .map(([id, qty]) => ({ id, qty, ing: ALL_INGREDIENTS.find(i => i.id === id) }))
          .filter(x => x.ing && x.qty > 0);
    if (items.length === 0) return;

    const totals = resolvedTotals || computeTotals(selections);
    const name = (saladName || '').trim() || (isAr ? 'سلطتي الجديدة' : 'My new salad');

    // Resolve ingredient catalog IDs from the backend (numeric DB ids). We
    // best-effort match by English name; if a match is missing the salad still
    // saves with the local labels (the server stores arbitrary ingredient
    // payloads inside the `ingredients` JSON column).
    let catalog = [];
    try { catalog = await window.api.listIngredients({ limit: 500 }); } catch (_) {}

    const payloadIngredients = items.map(({ ing, qty }) => {
      const match = catalog.find(c =>
        (c.nameEn && c.nameEn.toLowerCase() === ing.name.toLowerCase()) ||
        (c.name && c.name.toLowerCase() === ing.name.toLowerCase())
      );
      return {
        ingredientId: match ? match.id : null,
        name: ing.name,
        nameEn: ing.name,
        nameAr: ing.ar,
        category: ing.category,
        quantity: qty,
        calories: ing.calories * qty,
        protein: ing.protein * qty,
      };
    });

    try {
      await window.api.createSalad({
        name,
        nameEn: name,
        nameAr: name,
        ingredients: payloadIngredients,
        totalCalories: Math.round(totals.calories),
        totalProtein: +totals.protein.toFixed(1),
        totalCarbs: +totals.carbs.toFixed(1),
        totalFat: +totals.fat.toFixed(1),
        tags: [],
      });
      showToast(t.saveToast);
      setSaladName('');
      setSelections({});
      await reloadSaved();
      setView('saved');
    } catch (e) {
      console.error('[Saladizer] createSalad failed:', e && (e.status || e.message), e && e.data, e);
      const msg = (e && e.data && (e.data.error || e.data.message)) || '';
      showToast((isAr ? 'تعذّر حفظ السلطة' : 'Could not save salad') + (msg ? ` — ${msg}` : ''));
    }
  };

  const handleLogout = () => {
    window.api.logout();
    setUser(null);
    setSavedSalads([]);
    setAuthState('guest');
    setView('home');
  };

  const handleAccountDeleted = () => {
    // Token already cleared by the delete-account modal; just unmount the app.
    setUser(null);
    setSavedSalads([]);
    setAuthState('guest');
    setView('home');
    showToast(isAr ? 'تم حذف حسابك' : 'Account deleted');
  };

  // ── Notifications ─────────────────────────────────────────
  const [notifOpen, setNotifOpen] = React.useState(false);
  const [unreadCount, setUnreadCount] = React.useState(0);

  const reloadUnread = React.useCallback(async () => {
    if (authState !== 'authed') return;
    try {
      const r = await window.api.unreadNotificationsCount();
      setUnreadCount((r && typeof r.count === 'number') ? r.count : 0);
    } catch (_) {}
  }, [authState]);

  React.useEffect(() => {
    if (authState === 'authed') {
      reloadUnread();
      const t = setInterval(reloadUnread, 60000);
      return () => clearInterval(t);
    }
  }, [authState, reloadUnread]);

  const onNav = (v) => {
    // Leaving the builder clears the "from chef" flag so next manual visit is clean.
    if (v !== 'build') { setFromChef(false); setChefNote(null); setChefNutrition(null); }
    setView(v);
  };

  // ── Render ────────────────────────────────────────────────
  if (authState === 'loading') {
    return <div className="app-loading">{isAr ? 'جارٍ التحميل...' : 'Loading...'}</div>;
  }

  if (authState === 'guest') {
    return (
      <>
        <AuthScreen
          lang={lang}
          onAuthenticated={(u) => { setUser(u); setAuthState('authed'); }}
        />
        <TweaksPanel title="Tweaks">
          <TweakSection label="Display">
            <TweakRadio
              label="Language"
              value={tweak.lang}
              onChange={(v) => setTweak('lang', v)}
              options={[{ value: 'en', label: 'EN' }, { value: 'ar', label: 'ع AR' }]}
            />
            <TweakToggle
              label="Dark mode"
              value={tweak.dark}
              onChange={(v) => setTweak('dark', v)}
            />
          </TweakSection>
        </TweaksPanel>
      </>
    );
  }

  let viewEl;
  switch (view) {
    case 'home':
      viewEl = <DashboardView t={t} lang={lang} onNav={onNav} onOpenChef={() => setChefOpen(true)} user={user} savedSalads={savedSalads} />;
      break;
    case 'build':
      viewEl = <BuilderView
        t={t} lang={lang}
        selections={selections}
        setSelections={setSelections}
        saladName={saladName}
        setSaladName={setSaladName}
        onSave={handleSave}
        onOpenChef={() => setChefOpen(true)}
        user={user}
        extraCatalog={extraCatalog}
        setExtraCatalog={setExtraCatalog}
        fromChef={fromChef}
        chefNote={chefNote}
        chefNutrition={chefNutrition}
        onLeaveChefMode={() => { setFromChef(false); setChefNutrition(null); }}
      />;
      break;
    case 'explore':
      viewEl = <ExploreView t={t} lang={lang} onNav={onNav} user={user} />;
      break;
    case 'saved':
      viewEl = <SavedView t={t} lang={lang} savedSalads={savedSalads} loading={savedLoading} onNav={onNav} onReload={reloadSaved} />;
      break;
    case 'chefmake':
      viewEl = <ChefMakesMeASaladView
        t={t} lang={lang} user={user} onNav={onNav}
        setSelections={setSelections} setSaladName={setSaladName}
        setExtraCatalog={setExtraCatalog}
        setFromChef={setFromChef}
        setChefNote={setChefNote}
        setChefNutrition={setChefNutrition}
      />;
      break;
    case 'profile':
      viewEl = <ProfileView
        t={t}
        lang={lang}
        setLang={(l) => setTweak('lang', l)}
        tweak={tweak}
        setTweak={setTweak}
        user={user}
        setUser={setUser}
        savedSalads={savedSalads}
        onLogout={handleLogout}
        onAccountDeleted={handleAccountDeleted}
      />;
      break;
    default:
      viewEl = null;
  }

  return (
    <div className="app">
      <Sidebar view={view} onNav={onNav} lang={lang} t={t} savedCount={savedSalads.length} user={user} onUpgrade={() => { setView('profile'); setToast({ show: true, text: isAr ? 'افتح تطبيق الجوال لتفعيل Plus' : 'Open the mobile app to activate Plus' }); setTimeout(() => setToast({ show: false, text: '' }), 3500); }} />
      <div className="main">
        <TopBar
          lang={lang}
          setLang={(l) => setTweak('lang', l)}
          t={t}
          onOpenChef={() => setChefOpen(true)}
          user={user}
          onNav={onNav}
          onOpenNotifications={() => setNotifOpen(true)}
          unreadCount={unreadCount}
        />
        {viewEl}
      </div>

      <NotificationsDrawer
        open={notifOpen}
        onClose={() => { setNotifOpen(false); setUnreadCount(0); }}
        lang={lang}
      />

      {/* Floating Chef Saladizer trigger */}
      {!chefOpen && (
        <button className="chef-fab" onClick={() => setChefOpen(true)} title={t.chefName}>
          <Icon name="message-circle" size={26} color="#fff" />
        </button>
      )}

      <ChefPanel
        open={chefOpen}
        onClose={() => setChefOpen(false)}
        t={t} lang={lang}
        selections={selections}
      />

      <Toast text={toast.text} show={toast.show} />

      {/* Tweaks panel — language, dark, palette, density */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="Display">
          <TweakRadio
            label="Language"
            value={tweak.lang}
            onChange={(v) => setTweak('lang', v)}
            options={[{ value: 'en', label: 'EN' }, { value: 'ar', label: 'ع AR' }]}
          />
          <TweakToggle
            label="Dark mode"
            value={tweak.dark}
            onChange={(v) => setTweak('dark', v)}
          />
          <TweakRadio
            label="Palette"
            value={tweak.palette}
            onChange={(v) => setTweak('palette', v)}
            options={[
              { value: 'app',       label: 'App sage' },
              { value: 'marketing', label: 'Forest' },
            ]}
          />
        </TweakSection>
        <TweakSection label="Quick jump">
          <TweakButton label="Go to Builder"  onClick={() => setView('build')} />
          <TweakButton label="Go to Saved"    onClick={() => setView('saved')} />
          <TweakButton label="Open Chef"      onClick={() => setChefOpen(true)} />
          <TweakButton label="Reset bowl"     onClick={() => { setSelections({}); setSaladName(''); }} />
          <TweakButton label="Log out"        onClick={handleLogout} />
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
