// debug-hud.jsx — Sprint β passive observability overlay.
//
// Активация (опт-ин):
//   ?debug=1 в URL  ←  предпочтительно, чтобы случайно не включить
//   localStorage.setItem("debugHud", "1") в DevTools Console
//
// Принципы (из обсуждения β):
//   - Passive: НЕ trigger renders в обычных компонентах,
//             НЕ subscribes на каждое state change,
//             НЕ становится сам причиной lag.
//   - Reads only: poll-tick раз в 1 сек, читает из:
//                 window.queryClient._cache         (runtime.js)
//                 window.__chatScrollStats          (ChatScroll глобал)
//                 fetch-wrapper counter (внутри HUD).
//   - Никаких subscriptions/observers — только interval read.
//
// Размер: ~150 строк. Свой scope, не интегрируется с runtime.js.

(function () {
  "use strict";

  function isEnabled() {
    if (typeof window === "undefined") return false;
    try {
      const params = new URLSearchParams(window.location.search);
      if (params.get("debug") === "1") return true;
      if (window.localStorage && window.localStorage.getItem("debugHud") === "1") return true;
    } catch {}
    return false;
  }

  // Fetch counter — wrapper устанавливается один раз при mount Toaster'a.
  // Если кто-то ещё обернул fetch — это ОК, мы цепляемся сверху.
  let fetchCounter = { total: 0, cancelled: 0, last60s: [] };
  function _installFetchWatcher() {
    if (window.__hudFetchInstalled) return;
    window.__hudFetchInstalled = true;
    const orig = window.fetch;
    window.fetch = async function (input, init) {
      const startTs = Date.now();
      fetchCounter.total++;
      fetchCounter.last60s.push(startTs);
      // Прибиваем хвост старше 60 сек
      const cutoff = startTs - 60_000;
      while (fetchCounter.last60s.length && fetchCounter.last60s[0] < cutoff) {
        fetchCounter.last60s.shift();
      }
      if (init && init.signal) {
        init.signal.addEventListener("abort", () => {
          fetchCounter.cancelled++;
        });
      }
      try {
        return await orig.apply(this, arguments);
      } catch (e) {
        if (e && e.name === "AbortError") fetchCounter.cancelled++;
        throw e;
      }
    };
  }

  function _row(label, value, danger) {
    return React.createElement(
      "div",
      { className: "flex items-center justify-between gap-3" },
      React.createElement("span", { className: "text-zinc-500" }, label),
      React.createElement(
        "span",
        { className: danger ? "text-rose-300" : "text-zinc-200 tabular-nums" },
        value
      )
    );
  }

  function _section(title, children) {
    return React.createElement(
      "div",
      { className: "border-t border-zinc-800/60 pt-1.5 mt-1.5 first:border-0 first:pt-0 first:mt-0" },
      React.createElement(
        "div",
        { className: "text-[10px] uppercase tracking-wider text-zinc-600 mb-1" },
        title
      ),
      React.createElement("div", { className: "space-y-0.5" }, children)
    );
  }

  function DebugHud() {
    const [, force] = React.useState(0);
    const [collapsed, setCollapsed] = React.useState(false);

    React.useEffect(() => {
      _installFetchWatcher();
      const id = setInterval(() => force((n) => n + 1), 1000);
      return () => clearInterval(id);
    }, []);

    if (!isEnabled()) return null;

    // === Сбор данных (read-only) ===
    const qc = window.queryClient || { _cache: new Map(), _listeners: new Map() };
    const cacheEntries = qc._cache instanceof Map ? qc._cache.size : 0;
    const subscribers = qc._listeners instanceof Map
      ? Array.from(qc._listeners.values()).reduce((s, v) => s + (v ? v.size : 0), 0)
      : 0;

    const cs = window.__chatScrollStats || {};
    const pollingHidden = typeof document !== "undefined" ? document.hidden : false;

    if (collapsed) {
      return React.createElement(
        "button",
        {
          onClick: () => setCollapsed(false),
          className:
            "fixed bottom-3 right-3 z-[9998] px-2 py-1 rounded bg-zinc-900/90 border border-zinc-700 text-[10px] text-zinc-400 font-mono backdrop-blur",
          title: "Открыть Debug HUD",
        },
        "🔧 HUD"
      );
    }

    return React.createElement(
      "div",
      {
        className:
          "fixed bottom-3 right-3 z-[9998] w-[260px] bg-zinc-950/95 border border-zinc-800 rounded-lg p-2.5 text-[11px] font-mono backdrop-blur shadow-2xl pointer-events-auto",
      },
      React.createElement(
        "div",
        { className: "flex items-center justify-between mb-2 pb-1.5 border-b border-zinc-800/60" },
        React.createElement(
          "span",
          { className: "text-zinc-400 uppercase tracking-wider text-[10px]" },
          "Debug HUD"
        ),
        React.createElement(
          "button",
          {
            onClick: () => setCollapsed(true),
            className: "text-zinc-500 hover:text-zinc-300",
            title: "Свернуть",
          },
          "−"
        )
      ),
      _section("runtime", [
        _row("cache entries", cacheEntries),
        _row("subscribers", subscribers),
        _row("fetches / 60s", fetchCounter.last60s.length),
        _row("fetches total", fetchCounter.total),
        _row("cancelled", fetchCounter.cancelled, fetchCounter.cancelled > 100),
        _row("polling paused", pollingHidden ? "✓ (hidden)" : "—"),
      ]),
      _section("chat scroll", [
        _row(
          "chat id",
          cs.currentChatId ? String(cs.currentChatId).slice(0, 16) + "…" : "—"
        ),
        _row("messages", cs.messagesCount || 0),
        _row("atBottom", cs.atBottom ? "✓" : "—"),
        _row("hasMore", cs.hasMore ? "✓" : "—"),
        _row("loadingMore", cs.loadingMore ? "✓" : "—"),
        _row(
          "oldestTs",
          cs.oldestTs ? String(cs.oldestTs).slice(0, 16) : "—"
        ),
      ]),
      _section("β counters", [
        _row("merges", cs.merges || 0),
        _row("prepends", cs.prepends || 0),
        _row("scroll restores", cs.scrollRestores || 0),
        _row("media re-anchors", cs.mediaLoadRestores || 0),
        _row("stale ignored", cs.staleIgnored || 0, (cs.staleIgnored || 0) > 10),
      ])
    );
  }

  window.DebugHud = DebugHud;
})();
