// App — EchoWatch: onboarding (stack picker) → dashboard.
// Local prefs persist to localStorage; when logged in, stack syncs to the
// backend and the live alert feed replaces the bundled sample data.
const STORE = {
  read(key, fallback) {
    try {
      const v = localStorage.getItem('echowatch:' + key);
      return v == null ? fallback : JSON.parse(v);
    } catch (e) { return fallback; }
  },
  write(key, value) {
    try { localStorage.setItem('echowatch:' + key, JSON.stringify(value)); } catch (e) {}
  },
};

function EchoWatchApp() {
  const [lang, setLang] = React.useState(() => STORE.read('lang', 'en'));
  const [theme, setTheme] = React.useState(() => STORE.read('theme', 'dark'));
  const [selected, setSelected] = React.useState(() => STORE.read('stack', []));
  const [onboarded, setOnboarded] = React.useState(() => STORE.read('onboarded', false));
  const [session, setSession] = React.useState(() => STORE.read('session', null)); // { token, stake }
  const [me, setMe] = React.useState(null);        // server profile (incl. channels)
  const [feed, setFeed] = React.useState(null);    // live alerts; null = sample data
  const [walletOpen, setWalletOpen] = React.useState(false);
  const [scenario, setScenario] = React.useState('alerts'); // demo aid, not persisted

  React.useEffect(() => {
    document.documentElement.dataset.theme = theme;
    STORE.write('theme', theme);
  }, [theme]);
  React.useEffect(() => {
    document.documentElement.lang = lang === 'tw' ? 'zh-Hant' : lang === 'zh' ? 'zh-Hans' : lang;
    STORE.write('lang', lang);
  }, [lang]);
  React.useEffect(() => { STORE.write('stack', selected); }, [selected]);

  // Live feed, falling back silently to sample data when no backend is reachable.
  React.useEffect(() => {
    window.EWApi.fetchAlerts().then(setFeed).catch(() => setFeed(null));
  }, []);

  const refreshMe = React.useCallback(() => {
    if (!session) { setMe(null); return; }
    window.EWApi.me(session.token).then(setMe).catch((e) => {
      if (e.code === 'unauthorized') { // expired session
        setSession(null); STORE.write('session', null); setMe(null);
      }
    });
  }, [session]);
  React.useEffect(() => { refreshMe(); }, [refreshMe]);

  // First profile load: empty server stack adopts the local one; a non-empty
  // server stack wins (it is what notifications are filtered by).
  React.useEffect(() => {
    if (!me || !session) return;
    const server = me.stack || [];
    if (server.length === 0 && selected.length > 0) {
      window.EWApi.putMe(session.token, { stack: selected }).catch(() => {});
      setMe((m) => (m ? { ...m, stack: selected } : m));
    } else if (server.length > 0 && JSON.stringify(server) !== JSON.stringify(selected)) {
      setSelected(server);
    }
  }, [me && me.stakeAddress]); // run when a (new) profile lands, not on every edit

  // Single write path for the stack: local always, server when logged in.
  const updateStack = (updater) => {
    setSelected((prev) => {
      const ids = typeof updater === 'function' ? updater(prev) : updater;
      if (session) {
        window.EWApi.putMe(session.token, { stack: ids }).catch(() => {});
        setMe((m) => (m ? { ...m, stack: ids } : m));
      }
      return ids;
    });
  };

  const onLoggedIn = ({ token, user }) => {
    const sess = { token, stake: user.stakeAddress };
    setSession(sess);
    STORE.write('session', sess);
    setWalletOpen(false);
  };
  const logout = () => {
    setSession(null); setMe(null);
    STORE.write('session', null);
  };

  const t = window.EchoWatchI18n.makeT(lang);

  if (!onboarded) {
    return (
      <window.Onboarding
        t={t} lang={lang} setLang={setLang}
        onDone={(ids) => { updateStack(ids); setOnboarded(true); STORE.write('onboarded', true); }}
      />
    );
  }
  return (
    <>
      <window.Dashboard
        t={t} lang={lang} setLang={setLang}
        selected={selected} setSelected={updateStack}
        feed={feed} scenario={scenario} setScenario={setScenario}
        theme={theme} setTheme={setTheme}
        session={session} me={me} refreshMe={refreshMe}
        onConnect={() => setWalletOpen(true)} onLogout={logout}
      />
      <window.WalletModal open={walletOpen} onClose={() => setWalletOpen(false)} t={t} onLoggedIn={onLoggedIn} />
    </>
  );
}
window.EchoWatchApp = EchoWatchApp;
