/* global React, ReactDOM, useDeck, BriefView, DeckView, UpdatePill, Icons */
// Root shell: top bar with the Brief|Deck tab switcher, an error boundary so a
// single malformed row cannot blank the app, and the two views.
(() => {
  const e = React.createElement;

  class ErrorBoundary extends React.Component {
    constructor(props) { super(props); this.state = { err: null }; }
    static getDerivedStateFromError(err) { return { err }; }
    render() {
      if (this.state.err) {
        return e("div", { className: "load-error" },
          "something rendered wrong on this view.", e("br"),
          "reload, or switch tabs. (the data is fine.)");
      }
      return this.props.children;
    }
  }

  function freshnessOf(heartbeats) {
    if (!heartbeats || !heartbeats.length) return null;
    const latest = heartbeats.reduce((m, h) => (h.last_run_at > m ? h.last_run_at : m), "");
    if (!latest) return null;
    const then = new Date(latest.replace(" ", "T") + (latest.includes("Z") ? "" : "Z"));
    const hours = (Date.now() - then.getTime()) / 3600000;
    const label = then.toLocaleString("en-US", { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
    return { label, stale: hours > 30 };
  }

  // Brand mark: primary is 2C (reading-terminal, violet prompt + blinking
  // caret); 2A (clean "dujour.") is the alternate. Default 2C; switch by
  // appending ?brand=2a (it sticks in localStorage) or changing the default.
  function brandVariant() {
    try {
      const q = new URLSearchParams(location.search).get("brand");
      if (q === "2a" || q === "2c") { localStorage.setItem("dujour:brand", q); return q; }
      return localStorage.getItem("dujour:brand") || "2c";
    } catch { return "2c"; }
  }
  function Brand() {
    const v = brandVariant();
    const mark = v === "2a"
      ? e("span", { className: "dj-word" },
          e("span", { className: "dj-du" }, "du"), "jour",
          e("span", { className: "dj-dot" }, "."))
      : e("span", { className: "dj-mark", "aria-label": "dujour" },
          e("span", { className: "dj-prompt" }, ">"),
          e("span", { className: "dj-du" }, "du"),
          e("span", { className: "dj-rest" }, "jour"),
          e("span", { className: "dj-caret", "aria-hidden": "true" }));
    return e("div", { className: "brand" }, mark,
      e("span", { className: "zg-sub" }, "THE WEEK, DISTILLED"));
  }

  const TAB_KEY = "dujour:tab:v1";

  function App() {
    const [tab, setTab] = React.useState(() => {
      try { return localStorage.getItem(TAB_KEY) || "brief"; } catch { return "brief"; }
    });
    const setTabP = (t) => { setTab(t); try { localStorage.setItem(TAB_KEY, t); } catch { /* ignore */ } };
    const { data, error, loading } = useDeck(7, 21, 3);
    const counts = (data && data.counts) || {};
    const fresh = freshnessOf(data && data.heartbeats);

    if (error) {
      return e("div", { className: "load-error" }, "failed to load; check /api/deck and the D1 binding");
    }

    const tabBtn = (id, label, iconEl) => e("button", {
      className: `tab${tab === id ? " on" : ""}`, onClick: () => setTabP(id),
    }, iconEl, label);

    return e(React.Fragment, null,
      e("div", { className: "app" },
      e("header", { className: "topbar" },
        e(Brand),
        e("div", { className: "tabs", role: "tablist" },
          tabBtn("brief", "Brief", e("span", { className: "tab-dot" })),
          tabBtn("deck", "Deck", e(Icons.Grid, { size: 12 }))),
        e("div", { className: "topbar-stats" },
          !loading && tab === "deck" && e("span", { className: "tabnum hide-sm" },
            `${counts.news || 0} news · ${counts.tweets_window || 0} tweets · ${counts.podcasts || 0} pods`),
          fresh && e(React.Fragment, null,
            e("span", { className: `dot${fresh.stale ? " stale" : ""}` }),
            e("span", { className: "tabnum" }, `refreshed ${fresh.label}`)))),
      e("div", { className: "view" },
        e(ErrorBoundary, { key: tab },
          tab === "brief"
            ? e(BriefView, { synthesis: data && data.synthesis, loading })
            : e(DeckView, { data, loading })))),
      e(UpdatePill));
  }

  ReactDOM.createRoot(document.getElementById("root")).render(e(App));
})();
