/* global React */
const { useState, useEffect, useMemo } = React;

// ────────────────────────────────────────────────────────────
// App — главный контейнер с роутингом между экранами
// Phase 1 MVP: Лента / Карта / Статистика / Деталь события
// (subs / settings / about — отложено в Phase 2)
// ────────────────────────────────────────────────────────────
// Read initial screen from URL ?screen=... or Telegram start_param.
function __initialTab() {
  try {
    const params = new URLSearchParams(window.location.search || "");
    const fromUrl = params.get("screen");
    if (fromUrl) return fromUrl;
    const tg = window.Telegram?.WebApp;
    const startParam = tg?.initDataUnsafe?.start_param;
    if (startParam) return startParam;
  } catch (e) {}
  return "home";
}

// Theme override stored in localStorage. "auto" follows Telegram, "light"/
// "dark" force a fixed theme regardless of TG colorScheme.
function __readThemePref() {
  try { return localStorage.getItem("eq.theme") || "auto"; } catch (e) { return "auto"; }
}
function __saveThemePref(v) {
  try { localStorage.setItem("eq.theme", v); } catch (e) {}
}

// Home variant pref — A (default, scientific) / B (map-first) / C (minimal)
function __readHomeVariant() {
  try { return localStorage.getItem("eq.home-variant") || "A"; } catch (e) { return "A"; }
}

window.MiniApp = () => {
  const tg = window.TG;
  // Mini App auth gate: real Telegram clients (mobile AND Telegram Desktop)
  // expose a non-empty initData. A regular browser has none — there we must
  // NOT make authorized requests, NOT show global data as "yours", and NOT
  // surface a raw "missing tma authorization". Instead we render a clean gate
  // that sends the user to the bot.
  const inTelegram = !!(window.Telegram && window.Telegram.WebApp && window.Telegram.WebApp.initData);
  const [themePref, setThemePref] = useState(__readThemePref());
  const [tgDark, setTgDark] = useState(tg.dark);
  const dark = themePref === "auto" ? tgDark : themePref === "dark";
  const setDark = (next) => {
    // Manual toggle — store an explicit pref (light or dark) and exit auto.
    const v = next ? "dark" : "light";
    setThemePref(v);
    __saveThemePref(v);
  };

  // Onboarding gate: shown ONCE on first launch. Bypassed thereafter.
  const [needsOnboarding, setNeedsOnboarding] = useState(
    () => (window.__shouldShowOnboarding ? window.__shouldShowOnboarding() : false)
  );

  const [homeVariant, setHomeVariantState] = useState(__readHomeVariant());
  const setHomeVariant = (v) => {
    try { localStorage.setItem("eq.home-variant", v); } catch (e) {}
    setHomeVariantState(v);
  };

  const [tab, setTab] = useState(__initialTab()); // home | map | stats | digest | settings | about
  const [detailEvent, setDetailEvent] = useState(null);
  // When the alarm view is active, user can press "Карта эпицентра" to fall
  // through to the regular EventDetailScreen even though mag>=6.
  const [forceDetail, setForceDetail] = useState(false);
  // Tsunami detail screen visibility (overlay over detail/alarm).
  const [tsunamiForEvent, setTsunamiForEvent] = useState(null);
  const T = dark ? window.TOKENS.dark : window.TOKENS.light;

  // Subscribe to Telegram theme changes — only relevant in "auto" mode.
  useEffect(() => {
    if (!tg.onThemeChange) return;
    return tg.onThemeChange((isDark) => setTgDark(isDark));
  }, []);

  // Load data once on mount — only inside Telegram. Outside, we show the gate
  // and never touch Supabase/the backend.
  useEffect(() => { if (!inTelegram) return; window.DATA.reload(); }, []);

  // Pull user's mag_digest from backend on first mount, so the feed/digest
  // screens filter the same way as the Telegram digest. Silent on failure
  // (when opened outside Telegram, /status returns 401 and we just stay on
  // the default minimum magnitude — Mini App remains usable read-only).
  useEffect(() => {
    if (!inTelegram) return;
    if (!window.API || !window.DATA?.setUserMagFilter) return;
    window.API.getStatus()
      .then((s) => {
        if (s && typeof s.mag_digest === "number") {
          window.DATA.setUserMagFilter(s.mag_digest);
        }
      })
      .catch(() => {});
  }, []);

  // Reactive store
  const data = window.DATA.useDataState();

  // Telegram BackButton: visible whenever we're not on the home tab or in detail
  useEffect(() => {
    if (!tg.available) return;
    const inSubScreen = !!detailEvent || tab !== "home";
    if (inSubScreen) {
      tg.showBack();
      const off = tg.onBack(() => {
        if (detailEvent) setDetailEvent(null);
        else setTab("home");
      });
      return () => { off(); tg.hideBack(); };
    } else {
      tg.hideBack();
    }
  }, [detailEvent, tab]);

  const openEvent = (ev) => { setDetailEvent(ev); setForceDetail(false); };
  const closeDetail = () => { setDetailEvent(null); setForceDetail(false); };

  // Auth gate — opened outside Telegram (no initData). Rendered AFTER all hooks
  // so hook order stays stable. No data has been fetched in this case.
  if (!inTelegram) {
    return <GateScreen T={T} />;
  }

  // Loading screen
  if (data.loading && data.events.length === 0) {
    return <LoadingScreen T={T} />;
  }
  // Hard error: show banner but try to render whatever we have
  if (data.error && data.events.length === 0) {
    return <ErrorScreen T={T} error={data.error} onRetry={() => window.DATA.reload()} />;
  }

  // Onboarding takes over the whole screen on first launch
  if (needsOnboarding) {
    return (
      <window.OnboardingScreen T={T} dark={dark} onFinish={() => {
        if (window.__markOnboardingSeen) window.__markOnboardingSeen();
        setNeedsOnboarding(false);
      }} />
    );
  }

  // Tsunami detail overlay — shown over alarm/detail when user clicks the
  // tsunami warning. Fully covers the screen until back is pressed.
  if (tsunamiForEvent) {
    return (
      <window.TsunamiScreen T={T} dark={dark} ev={tsunamiForEvent}
        onBack={() => setTsunamiForEvent(null)} />
    );
  }

  let screen;
  if (detailEvent) {
    // Strong events get the dramatic Alarm view; "Карта эпицентра" inside
    // it sets forceDetail=true so we fall through to the full Leaflet detail.
    if (detailEvent.mag >= 6.0 && !forceDetail) {
      screen = <window.AlarmScreen T={T} dark={dark} ev={detailEvent}
        onBack={closeDetail}
        onShowDetail={() => setForceDetail(true)}
        onShowTsunami={() => setTsunamiForEvent(detailEvent)} />;
    } else {
      screen = <window.EventDetailScreen T={T} dark={dark} ev={detailEvent}
        onBack={closeDetail}
        onShowTsunami={() => setTsunamiForEvent(detailEvent)} />;
    }
  } else if (tab === "safety") {
    screen = <window.SafetyGuide T={T} dark={dark} onBack={() => setTab("settings")} />;
  } else if (tab === "map") {
    screen = <window.MapScreen T={T} dark={dark} onOpenEvent={openEvent} onBack={() => setTab("home")} />;
  } else if (tab === "stats") {
    screen = <window.StatsScreen T={T} dark={dark} onBack={() => setTab("home")} />;
  } else if (tab === "digest") {
    screen = <window.DigestScreen T={T} dark={dark} onBack={() => setTab("home")}
      onOpenEvent={openEvent} hours={12} />;
  } else if (tab === "settings") {
    screen = <window.SettingsScreen T={T} dark={dark} onBack={() => setTab("home")}
      onToggleTheme={() => setDark(!dark)}
      onOpenAbout={() => setTab("about")}
      onOpenSafety={() => setTab("safety")}
      homeVariant={homeVariant}
      onChangeHomeVariant={setHomeVariant} />;
  } else if (tab === "about") {
    screen = <window.AboutScreen T={T} dark={dark} onBack={() => setTab("settings")} />;
  } else {
    // Home — variant switchable via Settings.  Pass onOpenSettings so the
    // filter pill in Home A can jump straight to Settings.
    const goSettings = () => setTab("settings");
    if (homeVariant === "B" && window.HomeScreenB) {
      screen = <window.HomeScreenB T={T} dark={dark} onOpenEvent={openEvent}
        onOpenSettings={goSettings} />;
    } else if (homeVariant === "C" && window.HomeScreenC) {
      screen = <window.HomeScreenC T={T} dark={dark} onOpenEvent={openEvent}
        onOpenSettings={goSettings} />;
    } else {
      screen = <window.HomeScreenA T={T} dark={dark} onOpenEvent={openEvent}
        onOpenSettings={goSettings} />;
    }
  }

  return (
    <div style={{
      // Fixed viewport height (not minHeight!) so the inner flex layout
      // constrains scrolling to the content area only, leaving the bottom
      // tab bar fixed at the viewport bottom. With minHeight the entire
      // page extends and the bar scrolls with content.
      width: "100%", height: "100vh",
      display: "flex", flexDirection: "column",
      background: T.bg,
      fontFamily: 'Manrope, "Helvetica Neue", system-ui, sans-serif',
      color: T.text,
    }}>
      {/* Top bar — Telegram WebApp style */}
      <div style={{
        padding: "10px 14px", background: T.surface, borderBottom: `1px solid ${T.borderSoft}`,
        display: "flex", alignItems: "center", gap: 10, flexShrink: 0,
      }}>
        <div style={{
          width: 28, height: 28, borderRadius: 14,
          border: `1.5px solid ${T.accent}`, color: T.accent,
          display: "flex", alignItems: "center", justifyContent: "center",
        }}>
          {window.Icon.pulse(16)}
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 13, fontWeight: 600, letterSpacing: -0.1 }}>Сейсмомониторинг</div>
          <div style={{ fontSize: 10, color: T.textMuted, fontFamily: '"JetBrains Mono", monospace' }}>
            {window.CONFIG.CHANNEL}
          </div>
        </div>
        {!tg.available && (
          <button onClick={() => setDark(!dark)} title="Тема" style={{
            width: 32, height: 32, borderRadius: 16, border: `1px solid ${T.border}`,
            background: "transparent", color: T.text, cursor: "pointer", padding: 0,
            display: "flex", alignItems: "center", justifyContent: "center", fontSize: 14,
          }}>
            {dark ? "☀" : "☾"}
          </button>
        )}
      </div>

      {/* Main content */}
      <div style={{ flex: 1, overflow: "auto", overflowX: "hidden" }}>
        {screen}
      </div>

      {/* Bottom navigation */}
      {!detailEvent && (
        <div style={{
          background: T.surface, borderTop: `1px solid ${T.borderSoft}`,
          display: "flex", paddingBottom: 4, flexShrink: 0,
        }}>
          <window.TabButton T={T} active={tab === "home"} onClick={() => setTab("home")}
            icon={window.Icon.pulse(16)} label="Лента" />
          <window.TabButton T={T} active={tab === "digest"} onClick={() => setTab("digest")}
            icon={window.Icon.bell(16)} label="Сводка" />
          <window.TabButton T={T} active={tab === "map"} onClick={() => setTab("map")}
            icon={window.Icon.map(16)} label="Карта" />
          <window.TabButton T={T} active={tab === "stats"} onClick={() => setTab("stats")}
            icon={window.Icon.chart(16)} label="Статистика" />
          <window.TabButton T={T} active={tab === "settings" || tab === "about"}
            onClick={() => setTab("settings")}
            icon={window.Icon.settings(16)} label="Ещё" />
        </div>
      )}
    </div>
  );
};

// Shown when the Mini App is opened outside Telegram (no initData). Clean
// dead-end with a link to the bot — no data, no raw auth errors.
const GateScreen = ({ T }) => (
  <div style={{
    width: "100%", height: "100vh", background: T.bg, color: T.text,
    display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center",
    fontFamily: 'Manrope, "Helvetica Neue", system-ui, sans-serif', gap: 18, padding: 28, textAlign: "center",
  }}>
    <div style={{
      width: 56, height: 56, borderRadius: 28,
      border: `1.5px solid ${T.accent}`, color: T.accent,
      display: "flex", alignItems: "center", justifyContent: "center",
    }}>
      {window.Icon.pulse(28)}
    </div>
    <div style={{ fontSize: 18, fontWeight: 600, letterSpacing: -0.2 }}>Сейсмомониторинг</div>
    <div style={{ fontSize: 14, color: T.textDim, maxWidth: 300, lineHeight: 1.5 }}>
      Это мини-приложение открывается внутри Telegram. Запустите его через бота —
      так подгрузятся ваши настройки и персональная сводка.
    </div>
    <a href="https://t.me/SeismicAlert_Russia_bot" target="_blank" rel="noopener noreferrer"
      style={{
        marginTop: 4, padding: "12px 22px", borderRadius: 10,
        background: T.accent, color: "#fff", fontSize: 14, fontWeight: 600,
        textDecoration: "none", display: "inline-flex", alignItems: "center", gap: 8,
      }}>
      Открыть @SeismicAlert_Russia_bot
    </a>
  </div>
);

const LoadingScreen = ({ T }) => (
  <div style={{
    width: "100%", height: "100vh", background: T.bg, color: T.textDim,
    display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center",
    fontFamily: 'Manrope, system-ui, sans-serif', gap: 14,
  }}>
    <div style={{ display: "flex", alignItems: "center", gap: 10, color: T.accent }}>
      <window.LivePulse color={T.accent} size={10} />
      <span style={{ fontSize: 13, letterSpacing: 0.5, fontFamily: '"JetBrains Mono", monospace' }}>
        ЗАГРУЗКА ДАННЫХ
      </span>
    </div>
    <div style={{ fontSize: 11, color: T.textMuted, fontFamily: '"JetBrains Mono", monospace' }}>
      USGS · EMSC · Supabase
    </div>
  </div>
);

const ErrorScreen = ({ T, error, onRetry }) => (
  <div style={{
    width: "100%", height: "100vh", background: T.bg, color: T.text,
    display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center",
    fontFamily: 'Manrope, system-ui, sans-serif', gap: 14, padding: 24, textAlign: "center",
  }}>
    <div style={{ fontSize: 32 }}>⚠️</div>
    <div style={{ fontSize: 14 }}>Не удалось получить данные</div>
    <div style={{ fontSize: 11, color: T.textMuted, fontFamily: '"JetBrains Mono", monospace' }}>
      {error}
    </div>
    <button onClick={onRetry} style={{
      marginTop: 8, padding: "10px 20px", borderRadius: 8,
      border: `1px solid ${T.accent}`, background: T.accent, color: "#fff",
      fontSize: 13, fontWeight: 600, cursor: "pointer",
    }}>Повторить</button>
  </div>
);

// Bootstrap
// Babel-in-browser <script type="text/babel"> tags execute AFTER DOMContentLoaded
// has already fired, so listening to that event would never trigger. Instead
// render directly — by the time this code runs, the body (including #root) is
// fully parsed because the script tag is at the end of <body>.
function __bootstrap() {
  if (window.__bootStep) window.__bootStep("MOUNTING");
  const el = document.getElementById("root");
  if (!el) {
    console.error("[Mini App] #root not found");
    return;
  }
  try {
    const root = ReactDOM.createRoot(el);
    root.render(<window.MiniApp />);
    if (window.__bootStep) window.__bootStep("MOUNTED");
    console.log("[Mini App] mounted");
  } catch (e) {
    console.error("[Mini App] mount failed", e);
    if (window.__bootStep) window.__bootStep("MOUNT ERROR");
    el.innerHTML = `<pre style="color:#fff;padding:24px;font-family:monospace;font-size:12px;white-space:pre-wrap">Mount error:\n${(e && e.stack) || e}</pre>`;
  }
}
__bootstrap();
