/* global React */
// Data layer: one /api/deck fetch feeds the whole app, plus small helpers.
(() => {
  const { useState, useEffect } = React;

  function useDeck(days = 7, pdays = 21, ndays = 3) {
    const [state, setState] = useState({ data: null, error: null, loading: true });
    useEffect(() => {
      let alive = true;
      fetch(`/api/deck?days=${days}&pdays=${pdays}&ndays=${ndays}`, { cache: "no-store" })
        .then((r) => (r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`))))
        .then((data) => alive && setState({ data, error: null, loading: false }))
        .catch((error) => alive && setState({ data: null, error, loading: false }));
      return () => { alive = false; };
    }, [days, pdays, ndays]);
    return state;
  }

  const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

  // 5m / 3h under 24h, then "Jul 12"
  function relTime(unix) {
    const s = Math.max(1, Math.floor(Date.now() / 1000 - unix));
    if (s < 60) return `${s}s`;
    if (s < 3600) return `${Math.floor(s / 60)}m`;
    if (s < 86400) return `${Math.floor(s / 3600)}h`;
    const d = new Date(unix * 1000);
    return `${MONTHS[d.getMonth()]} ${d.getDate()}`;
  }

  function dayLabel(unix) {
    const d = new Date(unix * 1000);
    const today = new Date(); today.setHours(0, 0, 0, 0);
    const that = new Date(d); that.setHours(0, 0, 0, 0);
    const diff = Math.round((today - that) / 86400000);
    const wd = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][d.getDay()];
    if (diff === 0) return "Today";
    if (diff === 1) return "Yesterday";
    return `${wd} ${MONTHS[d.getMonth()]} ${d.getDate()}`;
  }
  function dayKey(unix) {
    const d = new Date(unix * 1000);
    return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
  }

  // 10.5K / 1.5M, one decimal, zero hidden by callers
  function abbrev(n) {
    if (n == null) return "";
    if (n < 1000) return String(n);
    if (n < 1e6) return `${(n / 1e3).toFixed(n < 10000 ? 1 : 0).replace(/\.0$/, "")}K`;
    return `${(n / 1e6).toFixed(1).replace(/\.0$/, "")}M`;
  }

  // total-minutes split so we never render an impossible "1h 60m"
  function fmtDuration(sec) {
    if (!sec) return "";
    const tm = Math.round(sec / 60);
    const h = Math.floor(tm / 60), m = tm % 60;
    if (h && m) return `${h}h ${m}m`;
    if (h) return `${h}h`;
    return `${m}m`;
  }

  function podDate(iso) {
    const [y, m, d] = (iso || "").split("-").map(Number);
    if (!y) return iso || "";
    const dt = new Date(y, m - 1, d);
    const today = new Date(); today.setHours(0, 0, 0, 0);
    const diff = Math.round((today - dt) / 86400000);
    if (diff === 0) return "Today";
    if (diff === 1) return "Yesterday";
    return `${MONTHS[dt.getMonth()]} ${dt.getDate()}`;
  }

  // deterministic channel hue (dylan-os idiom)
  function channelHue(name) {
    let h = 0;
    for (let i = 0; i < (name || "").length; i++) h = (h * 31 + name.charCodeAt(i)) % 360;
    return h;
  }

  Object.assign(window, {
    useDeck, relTime, dayLabel, dayKey, abbrev, fmtDuration, podDate, channelHue,
  });
})();
