// FORGE pump tenant — ActivityStream
// Live SSE-style scrolling list of newest 50 events.
// Week 1 stub: drives off PUMP_TENANT.ledger via forgeApi.subscribeEvents.
// Integration team will swap the stub for real /api/events/stream later.
//
// Babel-standalone IIFE pattern. NO module imports.
// Attaches: window.ActivityStream
(function () {
  // ── Defensive forgeApi stub for week 1 ───────────────────────────────
  // Replays PUMP_TENANT.ledger as fake SSE events at 1/sec.
  // Only installs if not already present (real API wins when wired).
  window.forgeApi = window.forgeApi || {};
  window.forgeApi.subscribeEvents = window.forgeApi.subscribeEvents || function (onEvent) {
    let i = 0;
    const ledger = (window.PUMP_TENANT && window.PUMP_TENANT.ledger) || [];
    const timer = setInterval(function () {
      if (i < ledger.length) {
        onEvent(ledger[i++]);
      } else {
        clearInterval(timer);
      }
    }, 1000);
    return function () { clearInterval(timer); };
  };
  window.forgeApi.me = window.forgeApi.me || function () { return Promise.resolve(null); };

  const { useState, useEffect, useRef } = React;

  // ── Helpers ───────────────────────────────────────────────────────────
  // Initials from "Karan V." → "KV"
  function initialsOf(name) {
    if (!name) return "??";
    const parts = String(name).trim().split(/\s+/);
    const first = parts[0] ? parts[0][0] : "";
    const last = parts.length > 1 ? parts[parts.length - 1][0] : "";
    return (first + last).toUpperCase();
  }

  // Mode → color (forge/plan/build/line/traveler)
  function modeColor(mode) {
    switch ((mode || "").toLowerCase()) {
      case "plan":     return "var(--info)";
      case "build":    return "var(--accent)";
      case "line":     return "var(--warn)";
      case "traveler": return "var(--ok)";
      case "forge":
      default:         return "var(--ink-3)";
    }
  }

  // Relative time — anchored to today (2026-05-18 per env). Prefers
  // Intl.RelativeTimeFormat for the active locale (e.g. "il y a 2 min",
  // "vor 3 Std", "2 दिन पहले") and falls back to compact English when
  // Intl.RelativeTimeFormat or forgeI18n isn't available.
  //
  // Intervals < 10 s floor to a localised "just now" — both because
  // "0 sec. ago" is grammatically awkward and because SSE replay clocks
  // briefly drift past Date.now() and would otherwise render as "0".
  function relTime(tsIso) {
    if (!tsIso) return "";
    const t = new Date(tsIso).getTime();
    if (Number.isNaN(t)) return tsIso;
    const now = (typeof window !== "undefined" && window.__forgeNowMs) || Date.now();
    const diffMs = now - t;
    if (diffMs < 10000) {
      const i18n = (typeof window !== "undefined") ? window.forgeI18n : null;
      if (i18n && typeof i18n.t === "function") {
        const s = i18n.t("time.just_now");
        if (s && s !== "time.just_now") return s;
      }
      return "just now";
    }
    const diffSec = Math.floor(diffMs / 1000);
    const loc = (window.forgeI18n && window.forgeI18n.locale && window.forgeI18n.locale()) || null;
    if (loc && typeof Intl !== "undefined" && typeof Intl.RelativeTimeFormat === "function") {
      try {
        const rtf = new Intl.RelativeTimeFormat(loc, { numeric: "always", style: "short" });
        if (diffSec < 60)      return rtf.format(-diffSec, "second");
        if (diffSec < 3600)    return rtf.format(-Math.floor(diffSec / 60), "minute");
        if (diffSec < 86400)   return rtf.format(-Math.floor(diffSec / 3600), "hour");
        if (diffSec < 2592000) return rtf.format(-Math.floor(diffSec / 86400), "day");
        return rtf.format(-Math.floor(diffSec / 2592000), "month");
      } catch (e) { /* fall through to English compact form */ }
    }
    if (diffSec < 60)       return diffSec + "s ago";
    if (diffSec < 3600)     return Math.floor(diffSec / 60) + "m ago";
    if (diffSec < 86400)    return Math.floor(diffSec / 3600) + "h ago";
    if (diffSec < 2592000)  return Math.floor(diffSec / 86400) + "d ago";
    return Math.floor(diffSec / 2592000) + "mo ago";
  }

  // Route an event ref to a dashboard path. ECO-0051 → /build/eco?id=ECO-0051, WO-44219 → /line/readiness etc.
  function refToPath(evt) {
    if (!evt || !evt.ref) return null;
    const ref = String(evt.ref);
    if (/^ECO-/.test(ref))       return "/build/eco?id=" + encodeURIComponent(ref);
    if (/^WO-/.test(ref))        return "/line/readiness?wo=" + encodeURIComponent(ref.split("·")[0].trim());
    if (/^RMA-/.test(ref))       return "/forge/field-issues?rma=" + encodeURIComponent(ref);
    if (/^RFQ-|^QT-|^PO-/.test(ref)) return "/forge/onboarding?ref=" + encodeURIComponent(ref);
    if (/^AUD-/.test(ref))       return "/auditor/ledger?ref=" + encodeURIComponent(ref);
    if (/^ROUT-|^QG-/.test(ref)) return "/build/gates?ref=" + encodeURIComponent(ref);
    if (/^DN-/.test(ref))        return "/line/readiness?dispatch=" + encodeURIComponent(ref);
    return null;
  }

  // ── Avatar ───────────────────────────────────────────────────────────
  function Avatar({ name }) {
    const _style = {
      width: 28, height: 28, borderRadius: 28,
      background: "var(--bg-3)",
      border: "1px solid var(--line-soft)",
      display: "inline-flex", alignItems: "center", justifyContent: "center",
      fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--ink-2)",
      flexShrink: 0,
    };
    return <span style={_style}>{initialsOf(name)}</span>;
  }

  // ── ModeBadge ────────────────────────────────────────────────────────
  function ModeBadge({ mode }) {
    const color = modeColor(mode);
    const _style = {
      display: "inline-flex", alignItems: "center",
      padding: "1px 6px", borderRadius: 3,
      border: "1px solid " + color, color: color,
      fontFamily: "var(--font-mono)", fontSize: 10,
      letterSpacing: "0.06em", textTransform: "uppercase",
      flexShrink: 0,
    };
    return <span style={_style}>{mode || "forge"}</span>;
  }

  // ── ActivityStream ───────────────────────────────────────────────────
  function ActivityStream({ max = 50, title = "Activity · live" }) {
    // Seed first paint with cached PUMP_TENANT.ledger (newest 50, no spinner).
    const seedLedger = (window.PUMP_TENANT && window.PUMP_TENANT.ledger) || [];
    const seedSorted = seedLedger.slice().sort(function (a, b) {
      return new Date(b.ts).getTime() - new Date(a.ts).getTime();
    }).slice(0, max);

    const [events, setEvents] = useState(seedSorted);

    // Throttle setState to 1/sec — incoming events accumulate in pendingRef,
    // flushed by an interval timer. Dedupe by event_id.
    const pendingRef = useRef([]);
    const seenRef = useRef(new Set(seedSorted.map(function (e) { return e.event_id; })));

    useEffect(function () {
      if (!window.forgeApi || typeof window.forgeApi.subscribeEvents !== "function") return;

      const unsub = window.forgeApi.subscribeEvents(function (evt) {
        if (!evt || !evt.event_id) return;
        if (seenRef.current.has(evt.event_id)) return;
        seenRef.current.add(evt.event_id);
        pendingRef.current.push(evt);
      });

      const flush = setInterval(function () {
        if (pendingRef.current.length === 0) return;
        const incoming = pendingRef.current;
        pendingRef.current = [];
        setEvents(function (prev) {
          const merged = incoming.concat(prev);
          merged.sort(function (a, b) {
            return new Date(b.ts).getTime() - new Date(a.ts).getTime();
          });
          return merged.slice(0, max);
        });
      }, 1000);

      return function () {
        clearInterval(flush);
        if (typeof unsub === "function") unsub();
      };
    }, [max]);

    function onRowClick(evt) {
      const path = refToPath(evt);
      if (!path) return;
      if (typeof window.navigate === "function") window.navigate(path);
      else window.location.hash = path;
    }

    return (
      <Panel
        title={title}
        right={<Tag>{events.length}/{max}</Tag>}
      >
        <div style={{ padding: 4, maxHeight: 360, overflowY: "auto" }}>
          {events.length === 0 && (
            <div className="muted" style={{ padding: 14, fontSize: 12 }}>
              Waiting for events…
            </div>
          )}
          {events.map(function (e) {
            const path = refToPath(e);
            const clickable = !!path;
            const _rowStyle = {
              display: "grid",
              gridTemplateColumns: "28px 1fr auto",
              gap: 10,
              padding: "8px 10px",
              alignItems: "center",
              borderBottom: "1px solid var(--line-soft)",
              cursor: clickable ? "pointer" : "default",
              background: "transparent",
              transition: "background .12s ease",
            };
            return (
              <div
                key={e.event_id}
                style={_rowStyle}
                onClick={function () { if (clickable) onRowClick(e); }}
                onMouseEnter={function (ev) { ev.currentTarget.style.background = "var(--bg-2)"; }}
                onMouseLeave={function (ev) { ev.currentTarget.style.background = "transparent"; }}
                title={clickable ? "Open " + e.ref : ""}
              >
                <Avatar name={e.actor} />
                <div style={{ minWidth: 0 }}>
                  <div style={{ display: "flex", gap: 6, alignItems: "center", marginBottom: 2 }}>
                    <span style={{ fontSize: 12, color: "var(--ink)", fontWeight: 500 }}>{e.actor}</span>
                    <ModeBadge mode={e.mode} />
                    <span
                      className="mono"
                      style={{ fontSize: 11, color: "var(--ink-4)" }}
                      title={(function () {
                        // Full TZ-aware timestamp on hover. forgeI18n resolves
                        // the active user's timezone from /api/auth/me.timezone
                        // and falls back to the tenant config timezone, then
                        // browser-local. Skip if forgeI18n hasn't loaded.
                        var i18n = (typeof window !== "undefined") ? window.forgeI18n : null;
                        if (i18n && typeof i18n.formatDateTime === "function") {
                          return i18n.formatDateTime(e.ts) || e.ts;
                        }
                        return e.ts || "";
                      })()}
                    >{relTime(e.ts)}</span>
                  </div>
                  <div
                    style={{
                      fontSize: 12,
                      color: "var(--ink-2)",
                      overflow: "hidden",
                      textOverflow: "ellipsis",
                      whiteSpace: "nowrap",
                    }}
                  >
                    {e.summary}
                  </div>
                </div>
                {e.ref && (
                  <span
                    className="mono"
                    style={{
                      fontSize: 11,
                      color: clickable ? "var(--accent-text)" : "var(--ink-4)",
                      flexShrink: 0,
                    }}
                  >
                    {e.ref}
                  </span>
                )}
              </div>
            );
          })}
        </div>
      </Panel>
    );
  }

  window.ActivityStream = ActivityStream;
})();
