import { useEffect, useRef, useState } from 'react';
import { getViewport } from './viewportLabelStore';
import { BUILD_ID, BUILD_TIME, DEPS } from './viewportBuild';

/**
 * STABLE VIEWPORT CORE — diagnostics drawer (workshop-owner only).
 * Live read-only view of the locked viewport health. Polls the shared store
 * on rAF. Provides Copy Diagnostics, Reset Camera, Disable/Reload optional
 * layers. Never offers "Restart App" as the normal recovery path.
 */

function Row({ label, value, ok }) {
  return (
    <div className="flex items-center justify-between border-b border-white/5 py-1.5 text-xs">
      <span className="text-slate-400">{label}</span>
      <span className={ok === false ? 'font-semibold text-amber-300' : ok === true ? 'font-semibold text-emerald-300' : 'font-mono text-slate-200'}>
        {value}
      </span>
    </div>
  );
}

export default function ViewportDiagnostics({ open, onClose, onResetCamera, onDisableLayers, onReloadLayers }) {
  const [, tick] = useState(0);
  const raf = useRef(0);
  useEffect(() => {
    if (!open) return;
    const loop = () => { tick((n) => (n + 1) & 0xffff); raf.current = requestAnimationFrame(loop); };
    raf.current = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf.current);
  }, [open]);

  if (!open) return null;
  const v = getViewport();
  const info = v.info || {};

  const rows = [
    ['App build ID', BUILD_ID],
    ['Build timestamp', BUILD_TIME],
    ['React', DEPS.react],
    ['ReactDOM', DEPS.reactDom],
    ['Three.js', DEPS.three],
    ['React Three Fiber', DEPS.fiber],
    ['Drei (core)', 'not imported'],
    ['WebGL context', v.contextLost ? 'Lost — recovering' : v.ready ? 'Active' : 'Initialising'],
    ['Renderer', v.gl ? v.gl.constructor.name : '—'],
    ['Camera', v.camera ? v.camera.constructor.name : '—'],
    ['Canvas count', '1 (locked)'],
    ['Controls instances', v.controlsCount],
    ['Draw calls', info.calls ?? '—'],
    ['Triangles', info.triangles ?? '—'],
    ['Geometry count', info.geometries ?? '—'],
    ['Texture count', info.textures ?? '—'],
    ['Procedural fallback', 'Loaded'],
    ['Last viewport error', v.error || '—'],
    ['Last context-loss event', v.contextLost ? 'recorded' : 'none'],
  ];

  const copy = () => {
    const text = rows.map(([k, val]) => `${k}: ${val}`).join('\n');
    navigator.clipboard?.writeText(text).catch(() => {});
  };

  return (
    <div className="fixed inset-0 z-50 flex justify-end bg-black/40" onClick={onClose}>
      <div className="h-full w-[90vw] max-w-sm overflow-y-auto border-l border-white/10 bg-[#0d1318] p-4" onClick={(e) => e.stopPropagation()}>
        <div className="mb-3 flex items-center justify-between">
          <h3 className="text-sm font-semibold text-white">Viewport Diagnostics</h3>
          <button onClick={onClose} className="icon-btn !min-h-9 !min-w-9">✕</button>
        </div>

        <div className="panel mb-3 p-3">
          {rows.map(([k, val]) => (
            <Row key={k} label={k} value={String(val)} ok={k === 'WebGL context' ? (v.contextLost ? false : v.ready) : k === 'Controls instances' ? v.controlsCount === 1 : undefined} />
          ))}
        </div>

        <div className="flex flex-wrap gap-2">
          <button onClick={copy} className="btn-secondary !px-3">Copy Diagnostics</button>
          <button onClick={onResetCamera} className="btn-secondary !px-3">Reset Camera</button>
          <button onClick={onDisableLayers} className="btn-secondary !px-3">Disable Optional Layers</button>
          <button onClick={onReloadLayers} className="btn-secondary !px-3">Reload Optional Layers</button>
        </div>

        <p className="mt-3 text-[10px] text-slate-500">
          StableViewportCore is locked. Optional feature failures disable only the failed layer — the procedural prosthetic stays visible.
        </p>
      </div>
    </div>
  );
}