<?php

ob_start();
?>
<div id="mbz-dev-pressure-widget"
     class="mt-2 -mx-6 px-2 pb-2 group-data-[collapsed=true]/collapse:hidden">
    <div class="rounded-2xl bg-elevated ring ring-divider/50 p-3 text-secondary"
         data-role="pressure-shell">
        <div class="flex items-center justify-between gap-2">
            <div class="text-[11px] font-semibold uppercase tracking-wide text-secondary/70">DOM pressure</div>
            <button type="button"
                    class="rounded px-1.5 py-0.5 text-[10px] font-medium text-secondary/70 ring-1 ring-divider hover:bg-muted"
                    title="Run full pressure report in console"
                    onclick="try { if (typeof window.mbzPagePressureReport === 'function') { window.mbzPagePressureReport(); } } catch (e) {}">
                Log
            </button>
        </div>

        <div class="mt-2 flex items-center justify-between gap-2 text-xs">
            <span class="inline-flex items-center gap-1.5 rounded-md px-1.5 py-0.5 ring-1 ring-divider"
                  data-role="level-chip">
                <span class="inline-block size-1.5 rounded-full bg-secondary/40" data-role="level-dot"></span>
                <span data-role="level">-</span>
            </span>
            <span class="text-[10px] text-secondary/60" data-role="updated">never</span>
        </div>

        <dl class="mt-2 grid grid-cols-2 gap-x-3 gap-y-1.5 text-[11px]">
            <div class="flex items-center justify-between gap-2">
                <dt class="text-secondary/70">Nodes</dt>
                <dd class="font-semibold tabular-nums" data-role="nodes">-</dd>
            </div>
            <div class="flex items-center justify-between gap-2">
                <dt class="text-secondary/70">Outside</dt>
                <dd class="font-semibold tabular-nums" data-role="outside">-</dd>
            </div>
            <div class="flex items-center justify-between gap-2">
                <dt class="text-secondary/70">HTMX</dt>
                <dd class="font-semibold tabular-nums" data-role="htmx">-</dd>
            </div>
            <div class="flex items-center justify-between gap-2">
                <dt class="text-secondary/70">Alpine</dt>
                <dd class="font-semibold tabular-nums" data-role="alpine">-</dd>
            </div>
            <div class="flex items-center justify-between gap-2">
                <dt class="text-secondary/70">Heap MB</dt>
                <dd class="font-semibold tabular-nums" data-role="heap">-</dd>
            </div>
            <div class="flex items-center justify-between gap-2">
                <dt class="text-secondary/70">Pages</dt>
                <dd class="font-semibold tabular-nums" data-role="pages">-</dd>
            </div>
        </dl>

        <div class="mt-2 h-1.5 w-full overflow-hidden rounded-full bg-muted">
            <div class="h-full rounded-full bg-secondary/50 transition-[width] duration-200"
                 data-role="outside-bar"
                 style="width: 0%"></div>
        </div>
        <div class="mt-1 text-[10px] text-secondary/60" data-role="outside-note">Outside DOM share: -</div>

        <div class="mt-2 rounded-lg bg-muted/60 p-1.5">
            <div class="flex items-center justify-between text-[10px] text-secondary/60">
                <span>Pressure trend</span>
                <span class="tabular-nums" data-role="trend-current">-</span>
            </div>
            <svg class="mt-1 block h-8 w-full" viewBox="0 0 100 24" preserveAspectRatio="none" aria-hidden="true">
                <polyline fill="none"
                          stroke="currentColor"
                          stroke-width="1.75"
                          stroke-linecap="round"
                          stroke-linejoin="round"
                          class="text-secondary/55"
                          data-role="trend-line"
                          points=""></polyline>
            </svg>
            <div class="text-[10px] text-secondary/55 tabular-nums" data-role="trend-range">min - max -</div>
        </div>
    </div>

    <script>
      (function () {
        var root = document.getElementById('mbz-dev-pressure-widget');
        if (!root) return;

        if (window.__mbzPressureWidget && typeof window.__mbzPressureWidget.detach === 'function') {
          try { window.__mbzPressureWidget.detach(); } catch (e0) { /* no-op */ }
        }

        var ctx = {
          timer: null,
          history: [],
          historyMax: 24,
          onAfterSettle: null,
          onModalCleanup: null,
          onVisible: null,
          onWindowLoad: null
        };

        function q(role) {
          return root.querySelector('[data-role="' + role + '"]');
        }

        function setText(role, value) {
          var el = q(role);
          if (!el) return;
          el.textContent = String(value);
        }

        function fmtInt(value) {
          var n = Number(value);
          if (!isFinite(n)) return '-';
          try {
            return Math.round(n).toLocaleString();
          } catch (e) {
            return String(Math.round(n));
          }
        }

        function pressureThresholds(scale) {
          var s = Number(scale);
          if (!isFinite(s) || s <= 0) s = 1;

          return {
            nodes: {
              watch: Math.round(8000 * s),
              high: Math.round(12000 * s),
              critical: Math.round(18000 * s)
            },
            htmx: {
              watch: Math.round(500 * s),
              high: Math.round(700 * s),
              critical: Math.round(1000 * s)
            },
            alpine: {
              watch: Math.round(150 * s),
              high: Math.round(200 * s),
              critical: Math.round(300 * s)
            },
            heapMB: {
              watch: 75,
              high: 150,
              critical: 300
            }
          };
        }

        function pressureMetricIndex(value, limits) {
          var n = Number(value);
          if (!isFinite(n) || n <= 0 || !limits) return 0;

          var watch = Math.max(1, Number(limits.watch) || 1);
          var high = Math.max(watch + 1, Number(limits.high) || (watch + 1));
          var critical = Math.max(high + 1, Number(limits.critical) || (high + 1));

          if (n <= watch) {
            return (n / watch) * 34;
          }
          if (n <= high) {
            return 35 + ((n - watch) / (high - watch)) * 24;
          }
          if (n <= critical) {
            return 60 + ((n - high) / (critical - high)) * 29;
          }

          return Math.min(100, 90 + ((n - critical) / critical) * 10);
        }

        function pressureLevelFloor(level) {
          var normalized = String(level || '').toLowerCase();
          if (normalized === 'critical') return 90;
          if (normalized === 'high') return 60;
          if (normalized === 'watch') return 35;
          return 0;
        }

        function derivePressureIndex(pressure) {
          if (!pressure) return NaN;

          var thresholds = pressureThresholds(pressure.scale);
          var index = Math.max(
            pressureMetricIndex(pressure.nodes, thresholds.nodes),
            pressureMetricIndex(pressure.htmx, thresholds.htmx),
            pressureMetricIndex(pressure.alpine, thresholds.alpine),
            pressureMetricIndex(pressure.heapMB, thresholds.heapMB)
          );

          index = Math.max(index, pressureLevelFloor(pressure.level));
          return Math.max(0, Math.min(100, index));
        }

        function safePressureReport() {
          if (typeof window.mbzPagePressureReport !== 'function') return null;

          var restore = null;
          try {
            if (window.console && typeof window.console.table === 'function') {
              restore = window.console.table;
              window.console.table = function () {};
            }
            return window.mbzPagePressureReport();
          } catch (e) {
            return null;
          } finally {
            if (restore) {
              window.console.table = restore;
            }
          }
        }

        function applyLevel(level, rawLevel) {
          var shell = q('pressure-shell');
          var dot = q('level-dot');
          var chip = q('level-chip');
          if (!shell || !dot || !chip) return;

          shell.classList.remove('ring-danger-600', 'ring-warning-500', 'ring-secondary', 'ring-divider/50');
          dot.classList.remove('bg-danger', 'bg-warning', 'bg-success', 'bg-secondary');

          var normalized = String(level || '').toLowerCase();
          if (normalized === 'critical' || normalized === 'high') {
            shell.classList.add('ring-danger-600');
            dot.classList.add('bg-danger');
          } else if (normalized === 'watch') {
            shell.classList.add('ring-warning-500');
            dot.classList.add('bg-warning');
          } else if (normalized === 'ok') {
            shell.classList.add('ring-divider/50');
            dot.classList.add('bg-success');
          } else {
            shell.classList.add('ring-divider/50');
            dot.classList.add('bg-secondary');
          }

          var label = normalized ? normalized.toUpperCase() : 'N/A';
          if (rawLevel && String(rawLevel).toLowerCase() !== normalized) {
            label += ' (' + String(rawLevel).toUpperCase() + ')';
          }
          setText('level', label);
        }

        function renderTrend() {
          var line = q('trend-line');
          if (!line) return;

          var values = ctx.history;
          if (!Array.isArray(values) || values.length === 0) {
            line.setAttribute('points', '');
            setText('trend-current', '-');
            setText('trend-range', 'min - max -');
            return;
          }

          var width = 100;
          var height = 24;
          var step = values.length > 1 ? width / (values.length - 1) : 0;
          var points = values.map(function (value, idx) {
            var v = Math.max(0, Math.min(100, Number(value) || 0));
            var x = (idx * step).toFixed(2);
            var y = (height - (v / 100) * height).toFixed(2);
            return x + ',' + y;
          }).join(' ');

          var latest = values[values.length - 1];
          var min = Math.min.apply(Math, values);
          var max = Math.max.apply(Math, values);

          line.setAttribute('points', points);
          line.classList.remove('text-danger', 'text-warning', 'text-success', 'text-secondary/55');
          if (latest >= 60) line.classList.add('text-danger');
          else if (latest >= 35) line.classList.add('text-warning');
          else if (latest > 0) line.classList.add('text-success');
          else line.classList.add('text-secondary/55');

          setText('trend-current', latest.toFixed(1) + '%');
          setText('trend-range', 'min ' + min.toFixed(1) + '% - max ' + max.toFixed(1) + '%');
        }

        function pushTrend(value) {
          var n = Number(value);
          if (!isFinite(n)) return;
          ctx.history.push(Math.max(0, Math.min(100, n)));
          if (ctx.history.length > ctx.historyMax) {
            ctx.history.splice(0, ctx.history.length - ctx.historyMax);
          }
          renderTrend();
        }

        function render(snapshot) {
          var p = snapshot && snapshot.pressure ? snapshot.pressure : null;
          if (!p) {
            setText('level', 'N/A');
            setText('updated', 'report unavailable');
            setText('nodes', '-');
            setText('outside', '-');
            setText('htmx', '-');
            setText('alpine', '-');
            setText('heap', '-');
            setText('pages', '-');
            setText('outside-note', 'Outside DOM share: -');
            var emptyBar = q('outside-bar');
            if (emptyBar) emptyBar.style.width = '0%';
            ctx.history = [];
            renderTrend();
            return;
          }

          var nodes = Number(p.nodes || 0);
          var outside = Number(p.outsidePageNodes || 0);
          var outsidePct = nodes > 0 ? Math.max(0, Math.min(100, (outside / nodes) * 100)) : 0;
          var pressurePct = derivePressureIndex(p);

          var pageCount = Array.isArray(snapshot.pages) ? snapshot.pages.length : 0;
          var protectedCount = Array.isArray(snapshot.pages)
            ? snapshot.pages.filter(function (row) { return !!row && !!row.protected; }).length
            : 0;

          applyLevel(p.level, p.rawLevel);
          setText('updated', new Date().toLocaleTimeString());
          setText('nodes', fmtInt(nodes));
          setText('outside', fmtInt(outside));
          setText('htmx', fmtInt(p.htmx || 0));
          setText('alpine', fmtInt(p.alpine || 0));
          setText('heap', (typeof p.heapMB === 'number' && isFinite(p.heapMB)) ? p.heapMB.toFixed(1) : '-');
          setText('pages', fmtInt(pageCount) + (pageCount ? ' (' + fmtInt(protectedCount) + '?)' : ''));

          var bar = q('outside-bar');
          if (bar) {
            bar.style.width = outsidePct.toFixed(1) + '%';
            bar.classList.remove('bg-danger', 'bg-warning', 'bg-success', 'bg-secondary');
            if (outsidePct >= 60) bar.classList.add('bg-danger');
            else if (outsidePct >= 35) bar.classList.add('bg-warning');
            else if (outsidePct > 0) bar.classList.add('bg-success');
            else bar.classList.add('bg-secondary');
          }
          setText('outside-note', 'Outside DOM share: ' + outsidePct.toFixed(1) + '%');
          pushTrend(pressurePct);
        }

        function refresh(force) {
          if (document.hidden && !force) return;
          render(safePressureReport());
        }

        ctx.onAfterSettle = function () { refresh(true); };
        ctx.onModalCleanup = function () { refresh(true); };
        ctx.onVisible = function () {
          if (!document.hidden) refresh(true);
        };
        ctx.onWindowLoad = function () { refresh(true); };

        document.body.addEventListener('htmx:afterSettle', ctx.onAfterSettle);
        document.body.addEventListener('mb:modal:cleanup', ctx.onModalCleanup);
        document.addEventListener('visibilitychange', ctx.onVisible);
        window.addEventListener('load', ctx.onWindowLoad);

        ctx.timer = window.setInterval(function () {
          refresh(false);
        }, 5000);

        refresh(true);

        window.__mbzPressureWidget = {
          refresh: function () { refresh(true); },
          detach: function () {
            try {
              if (ctx.timer) {
                window.clearInterval(ctx.timer);
                ctx.timer = null;
              }
              document.body.removeEventListener('htmx:afterSettle', ctx.onAfterSettle);
              document.body.removeEventListener('mb:modal:cleanup', ctx.onModalCleanup);
              document.removeEventListener('visibilitychange', ctx.onVisible);
              window.removeEventListener('load', ctx.onWindowLoad);
            } catch (e) { /* no-op */ }
          }
        };
      })();
    </script>
</div>
<?php
echo ob_get_clean();
