import { useEffect, useRef, useState, useCallback, useMemo } from 'react';
import { ShieldAlert, RotateCcw } from 'lucide-react';
import { Plane } from '@babylonjs/core';
import { createBabylonContext, destroyBabylonContext, probeWebGLSupport } from './BabylonSceneLifecycle';
import { applyViewPreset, setProjectionMode } from './BabylonCameraController';
import { buildProsthesis } from './ProceduralProsthesisV2';
import { buildMeasurementStations } from './MeasurementStationsV2';
import { buildConceptualCover } from './ConceptualCoverV2';
import { buildBranding } from './BrandingLayerV2';
import { buildDesignPreview } from './DesignPreviewLayer';
import { buildOssiguardConnector } from './OssiguardConnectorLayer';
import { buildHumanReference } from './HumanReferenceV2';
import { createSelectionManager } from './BabylonSelectionManager';
import { buildWorkshopOverlays } from './WorkshopOverlayLayerV2';
import { buildWorkshopAssembly } from './WorkshopAssemblyLayerV2';
import { buildWorkshopCover } from './WorkshopCoverLayerV2';
import DomLabelLayerV2 from './DomLabelLayerV2';
import { VIEWPORT_V2_BUILD_ID, VIEWPORT_V2_LABEL, BABYLON_VERSION } from './viewportV2Build';

const msg = (e) => (e && e.message ? e.message : String(e));

const DEFAULT_DISPLAY = {
  measurements: true,
  sensitive: true,
  keepOut: true,
  access: true,
  cover: true,
  movement: true,
  logo: true,
};


export default function BabylonViewportV2({
  viewCommand,
  compatibility = false,
  mode = 'cover',
  showAllLabels = false,
  humanReference = false,
  geometry = null,
  designConfig = null,
  measurementStations = null,
  display = DEFAULT_DISPLAY,
  orthographic = false,
  sectionCut = false,
  highlightedStation = -1,
  selectedAngle = null,
  accessPoints = [],
  keepOutZones = [],
  sensitiveZones = [],
  movementPositions = [],
  coverConfig = {},
  coverExploded = false,
  showWorkshopCover = false,
  assembly = [],
  assemblyExploded = false,
  showAssembly = false,
  allowOsseointegrationAssembly = false,
  selectedId: externalSelectedId = null,
  paintMode = false,
  transparency = 1,
  ossiguardProfile = null,
  showOssiguard = true,
  onSelectionChanged = null,
  onOverlaySelection = null,
  onSurfacePoint = null,
  onDiagnostics = null,
}) {
  const canvasRef = useRef(null);
  const containerRef = useRef(null);
  const ctxRef = useRef(null);
  const prosthesisRef = useRef(null);
  const stationsRef = useRef(null);
  const coverRef = useRef(null);
  const brandingRef = useRef(null);
  const designRef = useRef(null);
  const ossiguardRef = useRef(null);
  const humanRefRef = useRef(null);
  const overlayRef = useRef(null);
  const assemblyRef = useRef(null);
  const workshopCoverRef = useRef(null);
  const selectionRef = useRef(null);
  const roRef = useRef(null);
  const resizeHandlerRef = useRef(null);
  const destroyedRef = useRef(false);

  const [attempt, setAttempt] = useState(0);
  const [engineError, setEngineError] = useState(null);
  const [layerErrors, setLayerErrors] = useState({
    prosthesis: null,
    stations: null,
    cover: null,
    branding: null,
    design: null,
    ossiguard: null,
    workshopOverlay: null,
    assembly: null,
    workshopCover: null,
  });
  const [labels, setLabels] = useState([]);
  const [selectedId, setSelectedId] = useState(null);

  // Refs mirror state so the diagnostics interval always reads fresh values.
  const compatRef = useRef(compatibility);
  const orthographicRef = useRef(orthographic);
  const paintModeRef = useRef(paintMode);
  const surfacePointRef = useRef(onSurfacePoint);
  const overlaySelectionRef = useRef(onOverlaySelection);
  const selectionChangedRef = useRef(onSelectionChanged);
  const layerErrorsRef = useRef(layerErrors);
  const engineErrorRef = useRef(engineError);

  useEffect(() => { compatRef.current = compatibility; }, [compatibility]);
  useEffect(() => { orthographicRef.current = orthographic; }, [orthographic]);
  useEffect(() => { paintModeRef.current = paintMode; }, [paintMode]);
  useEffect(() => { surfacePointRef.current = onSurfacePoint; }, [onSurfacePoint]);
  useEffect(() => { overlaySelectionRef.current = onOverlaySelection; }, [onOverlaySelection]);
  useEffect(() => { selectionChangedRef.current = onSelectionChanged; }, [onSelectionChanged]);
  useEffect(() => { layerErrorsRef.current = layerErrors; }, [layerErrors]);
  useEffect(() => { engineErrorRef.current = engineError; }, [engineError]);

  useEffect(() => {
    setSelectedId(
      externalSelectedId || null
    );
  }, [externalSelectedId]);

  const buildDiagnostics = useCallback(() => {
    const ctx = ctxRef.current;
    if (!ctx) return null;
    const { scene, camera, canvas } = ctx;
    const compat = compatRef.current;
    const errs = layerErrorsRef.current;
    const activeLayers = [];
    if (prosthesisRef.current) activeLayers.push('Prosthesis');
    if (stationsRef.current && !compat) activeLayers.push('Measurement stations');
    if (coverRef.current && !compat) activeLayers.push('Conceptual cover');
    if (brandingRef.current && !compat) activeLayers.push('Branding');
    if (designRef.current && !compat) activeLayers.push('Design preview');
    if (ossiguardRef.current && !compat) activeLayers.push('Ossiguard connector');
    if (overlayRef.current && !compat) activeLayers.push('Workshop overlays');
    if (assemblyRef.current && !compat) activeLayers.push('Workshop assembly');
    if (workshopCoverRef.current && !compat) activeLayers.push('Workshop cover');

    const optionalError =
      errs.prosthesis ||
      errs.stations ||
      errs.cover ||
      errs.branding ||
      errs.design ||
      errs.ossiguard ||
      errs.workshopOverlay ||
      errs.assembly ||
      errs.workshopCover ||
      null;
    return {
      implementation: VIEWPORT_V2_LABEL,
      babylonVersion: BABYLON_VERSION,
      engineInstances: 1,
      sceneInstances: 1,
      canvasInstances: 1,
      activeCamera: 'ArcRotateCamera',
      graphicsApi: ctx.engineMode || 'unknown',
      webgl2Available: !!ctx.webglSupport?.webgl2,
      webgl1Available: !!ctx.webglSupport?.webgl1,
      controlsAttached: !!(camera && canvas && canvas.isConnected),
      canvasConnected: !!(canvas && canvas.isConnected),
      canvasWidth: canvas ? canvas.clientWidth : 0,
      canvasHeight: canvas ? canvas.clientHeight : 0,
      renderLoopActive: !destroyedRef.current,
      resizeObservers: roRef.current ? 1 : 0,
      meshCount: scene ? scene.meshes.length : 0,
      activeLayers,
      prosthesisLoaded: !!prosthesisRef.current,
      overlaySpatialMissing: overlayRef.current?.missingSpatial?.length || 0,
      coreError: engineErrorRef.current || null,
      optionalError,
      buildId: VIEWPORT_V2_BUILD_ID,
    };
  }, []);

  // --- Engine + scene init: runs once per attempt. Cleanup order is strict. ---
  useEffect(() => {
    destroyedRef.current = false;
    const canvas = canvasRef.current;
    let ctx = null;
    let initError = null;

    try {
      ctx = createBabylonContext(canvas);
    } catch (e) {
      initError = msg(e);
      setEngineError(initError);
      ctx = null;
    }

    if (!ctx) {
      if (!initError) {
        setEngineError(
          canvas && canvas.isConnected
            ? `Canvas is connected but Babylon returned no graphics context (${canvas.clientWidth}×${canvas.clientHeight})`
            : 'Babylon canvas is not connected'
        );
      }

      return;
    }
    ctxRef.current = ctx;
    const { engine, scene } = ctx;
    const compat = compatRef.current;

    const errs = {
      prosthesis: null,
      stations: null,
      cover: null,
      branding: null,
      design: null,
      ossiguard: null,
      workshopOverlay: null,
    };
    const allLabels = [];

    // Each optional layer is isolated — failure disables only that layer.
    try {
      const p = buildProsthesis(scene, geometry);
      prosthesisRef.current = p;
      allLabels.push(...p.labels);
    } catch (e) { errs.prosthesis = msg(e); }

    if (!compat) {
      try {
        const s = buildMeasurementStations(scene, measurementStations);
        stationsRef.current = s;
        allLabels.push(...s.labels);
      } catch (e) { errs.stations = msg(e); }
      try {
        const c = buildConceptualCover(scene, geometry, designConfig);
        coverRef.current = c;
        allLabels.push(c.label);
      } catch (e) { errs.cover = msg(e); }
      try {
        const b = buildBranding(scene, designConfig || {});
        brandingRef.current = b;
        allLabels.push(b.label);
      } catch (e) { errs.branding = msg(e); }
      try {
        const d = buildDesignPreview(scene, geometry, designConfig);
        designRef.current = d;
        allLabels.push(d.label);
      } catch (e) { errs.design = msg(e); }
      try {
        if (showOssiguard && ossiguardProfile) {
          const og = buildOssiguardConnector(scene, geometry, ossiguardProfile);
          ossiguardRef.current = og;
          allLabels.push(...og.labels);
        }
      } catch (e) { errs.ossiguard = msg(e); }
    }
    try {
      const h = buildHumanReference(scene);
      humanRefRef.current = h;
    } catch (e) { /* human reference is optional */ }

    setLayerErrors(errs);
    setLabels(allLabels);

    try {
      selectionRef.current = createSelectionManager(
        scene,
        (meta, pickedMesh, pickedPoint) => {
          if (destroyedRef.current) return;

          if (!meta) {
            setSelectedId(null);
            selectionChangedRef.current?.(null);
            overlaySelectionRef.current?.(null);
            return;
          }

          if (
            paintModeRef.current &&
            meta.type === 'prosthesisPart' &&
            pickedPoint
          ) {
            surfacePointRef.current?.(pickedPoint);
            return;
          }

          if (
            meta.type === 'access' ||
            meta.type === 'keepout' ||
            meta.type === 'sensitive' ||
            meta.type === 'movement'
          ) {
            setSelectedId(meta.selectionId || null);
            overlaySelectionRef.current?.(meta);
            return;
          }

          setSelectedId(
            meta.partId ||
            meta.stationId ||
            null
          );

          selectionChangedRef.current?.(meta);
        }
      );
    } catch (_) { /* selection is optional */ }

    engine.runRenderLoop(() => {
      if (destroyedRef.current) return;
      try { scene.render(); } catch (_) {}
    });

    const container = containerRef.current;
    const onResize = () => {
      if (destroyedRef.current) return;
      const c = ctxRef.current;
      if (!c || !c.engine || !c.canvas || !c.canvas.isConnected) return;
      const r = container ? container.getBoundingClientRect() : null;
      if (!r || r.width <= 0 || r.height <= 0) return;
      try { c.engine.resize(); } catch (_) {}

      try {
        setProjectionMode(
          c.camera,
          orthographicRef.current,
          c.canvas
        );
      } catch (_) {}
    };
    if (container && typeof ResizeObserver !== 'undefined') {
      roRef.current = new ResizeObserver(onResize);
      roRef.current.observe(container);
    }
    resizeHandlerRef.current = onResize;
    window.addEventListener('resize', onResize);

    const diagTimer = setInterval(() => {
      if (destroyedRef.current) return;
      const snap = buildDiagnostics();
      if (snap) onDiagnostics && onDiagnostics(snap);
    }, 500);
    const initial = buildDiagnostics();
    if (initial) onDiagnostics && onDiagnostics(initial);

    return () => {
      destroyedRef.current = true;
      clearInterval(diagTimer);
      try { engine.stopRenderLoop(); } catch (_) {}
      try { if (selectionRef.current) { selectionRef.current.dispose(); selectionRef.current = null; } } catch (_) {}
      try { if (prosthesisRef.current) { prosthesisRef.current.dispose(); prosthesisRef.current = null; } } catch (_) {}
      try { if (stationsRef.current) { stationsRef.current.dispose(); stationsRef.current = null; } } catch (_) {}
      try { if (coverRef.current) { coverRef.current.dispose(); coverRef.current = null; } } catch (_) {}
      try { if (brandingRef.current) { brandingRef.current.dispose(); brandingRef.current = null; } } catch (_) {}
      try { if (designRef.current) { designRef.current.dispose(); designRef.current = null; } } catch (_) {}
      try { if (ossiguardRef.current) { ossiguardRef.current.dispose(); ossiguardRef.current = null; } } catch (_) {}
      try { if (humanRefRef.current) { humanRefRef.current.dispose(); humanRefRef.current = null; } } catch (_) {}
      try { if (overlayRef.current) { overlayRef.current.dispose(); overlayRef.current = null; } } catch (_) {}
      try { if (roRef.current) { roRef.current.disconnect(); roRef.current = null; } } catch (_) {}
      try { if (resizeHandlerRef.current) { window.removeEventListener('resize', resizeHandlerRef.current); resizeHandlerRef.current = null; } } catch (_) {}
      destroyBabylonContext(ctx);
      ctxRef.current = null;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [attempt]);

  // --- View commands (reset/front/side/top) ---
  useEffect(() => {
    if (!viewCommand || !ctxRef.current) return;
    applyViewPreset(ctxRef.current.camera, viewCommand.preset);
  }, [viewCommand]);

  // --- Perspective / orthographic projection ---
  useEffect(() => {
    const ctx = ctxRef.current;
    if (!ctx) return;

    try {
      setProjectionMode(
        ctx.camera,
        orthographic,
        ctx.canvas
      );
    } catch (_) {}
  }, [orthographic]);

  // --- Real Babylon section cut ---
  useEffect(() => {
    const ctx = ctxRef.current;
    if (!ctx) return;

    try {
      ctx.scene.clipPlane =
        sectionCut && !compatibility
          ? new Plane(1, 0, 0, 0)
          : null;
    } catch (_) {}
  }, [sectionCut, compatibility]);

  // --- Mode + compatibility visibility (no engine/scene recreation) ---
  useEffect(() => {
    const ctx = ctxRef.current;
    if (!ctx) return;

    const cover = coverRef.current;
    const brand = brandingRef.current;
    const design = designRef.current;
    const ossiguard = ossiguardRef.current;
    const stations = stationsRef.current;
    const human = humanRefRef.current;
    const overlay = overlayRef.current;

    if (compatibility) {
      cover?.setVisible(false);
      brand?.setVisible(false);
      design?.setVisible(false);
      ossiguard?.setVisible(false);
      stations?.setVisible(false);
      human?.setVisible(false);
      overlay?.setVisibility(display, true);

      ctx.hemi.intensity = 0.95;
      ctx.dir.intensity = 0.25;
    } else {
      const coverMode =
        mode === 'cover' ||
        mode === 'fit';

      const coverOn =
        coverMode &&
        display.cover !== false;

      const measurementsOn =
        display.measurements !== false &&
        (mode === 'internal' || mode === 'measure');

      cover?.setVisible(coverOn);
      design?.setVisible(coverOn);

      brand?.setVisible(
        coverOn &&
        display.logo !== false
      );

      ossiguard?.setVisible(
        showOssiguard &&
        coverOn
      );

      stations?.setVisible(measurementsOn);

      human?.setVisible(
        humanReference ||
        mode === 'fit'
      );

      overlay?.setVisibility(display, false);

      ctx.hemi.intensity = 0.95;
      ctx.dir.intensity = 0.95;
    }
  }, [
    compatibility,
    mode,
    humanReference,
    showOssiguard,
    display,
  ]);

  // --- Workshop measurement records can arrive after engine creation. ---
  // Rebuild only the station layer; never recreate the Babylon engine/scene.
  useEffect(() => {
    const ctx = ctxRef.current;
    if (!ctx) return;

    try {
      if (stationsRef.current) {
        stationsRef.current.dispose();
        stationsRef.current = null;
      }

      const nextStations = buildMeasurementStations(ctx.scene, measurementStations);
      stationsRef.current = nextStations;

      nextStations.setVisible(
        !compatibility &&
        display.measurements !== false &&
        (mode === 'internal' || mode === 'measure')
      );

      nextStations.setHighlighted?.(highlightedStation);

      setLabels((current) => [
        ...current.filter((label) => {
          const kind = label.kind || 'part';
          return kind !== 'station' && kind !== 'dim';
        }),
        ...nextStations.labels,
      ]);

      setLayerErrors((current) => ({ ...current, stations: null }));
    } catch (e) {
      setLayerErrors((current) => ({ ...current, stations: msg(e) }));
    }
  }, [measurementStations]);

  // --- Guided measurement station highlight ---
  useEffect(() => {
    try {
      stationsRef.current?.setHighlighted?.(
        highlightedStation
      );
    } catch (_) {}
  }, [highlightedStation]);

  // --- Workshop safety/movement overlays ---
  useEffect(() => {
    const ctx = ctxRef.current;
    if (!ctx) return;

    try {
      if (overlayRef.current) {
        overlayRef.current.dispose();
        overlayRef.current = null;
      }

      const overlay = buildWorkshopOverlays(
        ctx.scene,
        {
          accessPoints,
          keepOutZones,
          sensitiveZones,
          movementPositions,
        }
      );

      overlayRef.current = overlay;

      overlay.setVisibility(
        display,
        compatibility
      );

      overlay.setSelected?.(selectedId);
      overlay.setSelectedAngle?.(selectedAngle);

      const missingLabels = (
        overlay.missingSpatial || []
      ).map((entry, i) => ({
        id: `safety-missing-${entry.type}-${entry.index}`,
        position: [
          0.85,
          5.85 - i * 0.17,
          0,
        ],
        text: `${entry.label}: 3D position unavailable`,
        kind: 'safety-warning',
        tone: 'amber',
      }));

      setLabels((current) => [
        ...current.filter((label) => ![
          'access',
          'keepout',
          'sensitive',
          'movement',
          'safety-warning',
        ].includes(label.kind)),
        ...overlay.labels,
        ...missingLabels,
      ]);

      setLayerErrors((current) => ({
        ...current,
        workshopOverlay: null,
      }));
    } catch (e) {
      setLayerErrors((current) => ({
        ...current,
        workshopOverlay: msg(e),
      }));
    }

    return () => {
      try {
        overlayRef.current?.dispose();
      } catch (_) {}

      overlayRef.current = null;
    };
  }, [
    accessPoints,
    keepOutZones,
    sensitiveZones,
    movementPositions,
  ]);

  useEffect(() => {
    try {
      overlayRef.current?.setSelected?.(
        selectedId
      );
    } catch (_) {}
  }, [selectedId]);

  useEffect(() => {
    try {
      overlayRef.current?.setSelectedAngle?.(
        selectedAngle
      );
    } catch (_) {}
  }, [selectedAngle]);

  // --- Workshop Cover Builder layer ---
  useEffect(() => {
    const ctx = ctxRef.current;

    if (!ctx) return;

    try {
      if (workshopCoverRef.current) {
        workshopCoverRef.current.dispose();
        workshopCoverRef.current = null;
      }

      setLabels(current =>
        current.filter(
          label =>
            label.kind !== 'cover-control' &&
            !(
              label.kind === 'safety-warning' &&
              String(label.id || '').startsWith(
                'workshop-cover-'
              )
            )
        )
      );

      if (
        compatibility ||
        !showWorkshopCover
      ) {
        coverRef.current
          ?.setVisible?.(
            !compatibility &&
            display.cover !== false
          );

        setLayerErrors(current => ({
          ...current,
          workshopCover: null,
        }));

        return;
      }

      /*
       * Hide the older generic cover while the live
       * Cover Builder preview owns the cosmetic shell.
       */
      coverRef.current
        ?.setVisible?.(false);

      const next =
        buildWorkshopCover(
          ctx.scene,
          geometry,
          coverConfig,
          {
            exploded:
              coverExploded,
            sensitiveZones,
          }
        );

      workshopCoverRef.current =
        next;

      next.setVisible?.(
        display.cover !== false
      );

      const numeric =
        Number(transparency);

      next.setOpacity?.(
        Number.isFinite(numeric)
          ? Math.max(
              0.1,
              Math.min(1, numeric)
            )
          : 1
      );

      setLabels(current => [
        ...current.filter(
          label =>
            label.kind !==
              'cover-control' &&
            !(
              label.kind ===
                'safety-warning' &&
              String(
                label.id || ''
              ).startsWith(
                'workshop-cover-'
              )
            )
        ),
        ...next.labels,
      ]);

      setLayerErrors(current => ({
        ...current,
        workshopCover: null,
      }));
    } catch (e) {
      setLayerErrors(current => ({
        ...current,
        workshopCover: msg(e),
      }));
    }

    return () => {
      try {
        workshopCoverRef.current
          ?.dispose();
      } catch (_) {}

      workshopCoverRef.current =
        null;
    };
  }, [
    coverConfig,
    coverExploded,
    showWorkshopCover,
    geometry,
    sensitiveZones,
    compatibility,
    attempt,
  ]);

  useEffect(() => {
    try {
      workshopCoverRef.current
        ?.setVisible?.(
          !compatibility &&
          display.cover !== false
        );
    } catch (_) {}
  }, [
    display.cover,
    compatibility,
  ]);

  // --- Workshop assembly layer ---
  useEffect(() => {
    const ctx = ctxRef.current;

    if (!ctx) return;

    try {
      if (assemblyRef.current) {
        assemblyRef.current.dispose();
        assemblyRef.current = null;
      }

      setLabels(current =>
        current.filter(
          label =>
            label.kind !== 'assembly' &&
            label.kind !== 'assembly-warning'
        )
      );

      if (
        compatibility ||
        !showAssembly ||
        !Array.isArray(assembly) ||
        assembly.length === 0
      ) {
        setLayerErrors(current => ({
          ...current,
          assembly: null,
        }));

        return;
      }

      const next =
        buildWorkshopAssembly(
          ctx.scene,
          assembly,
          {
            exploded:
              assemblyExploded,
            allowOsseointegration:
              allowOsseointegrationAssembly,
          }
        );

      assemblyRef.current = next;

      next.setVisible?.(true);

      next.setSelected?.(
        externalSelectedId ||
        selectedId
      );

      setLabels(current => [
        ...current.filter(
          label =>
            label.kind !== 'assembly' &&
            label.kind !==
              'assembly-warning'
        ),
        ...next.labels,
        ...next.warnings,
      ]);

      setLayerErrors(current => ({
        ...current,
        assembly: null,
      }));
    } catch (e) {
      setLayerErrors(current => ({
        ...current,
        assembly: msg(e),
      }));
    }

    return () => {
      try {
        assemblyRef.current?.dispose();
      } catch (_) {}

      assemblyRef.current = null;
    };
  }, [
    assembly,
    assemblyExploded,
    showAssembly,
    allowOsseointegrationAssembly,
    compatibility,
    attempt,
  ]);

  useEffect(() => {
    try {
      assemblyRef.current
        ?.setSelected?.(
          externalSelectedId ||
          selectedId
        );
    } catch (_) {}
  }, [
    externalSelectedId,
    selectedId,
  ]);

  // --- Workshop transparency updates without engine recreation. ---
  useEffect(() => {
    const cover = coverRef.current;
    const workshopCover =
      workshopCoverRef.current;
    const prosthesis = prosthesisRef.current;

    const numeric = Number(transparency);
    const opacity = Number.isFinite(numeric)
      ? Math.max(0.1, Math.min(1, numeric))
      : 1;

    const effectiveOpacity =
      compatibility ? 1 : opacity;

    try {
      cover?.setOpacity?.(
        effectiveOpacity
      );
    } catch (_) {}

    try {
      workshopCover?.setOpacity?.(
        effectiveOpacity
      );
    } catch (_) {}

    try {
      const referenceOpacity =
        showAssembly &&
        Array.isArray(assembly) &&
        assembly.length > 0 &&
        !compatibility
          ? Math.min(
              effectiveOpacity,
              0.22
            )
          : effectiveOpacity;

      prosthesis?.setOpacity?.(
        referenceOpacity
      );
    } catch (_) {}
  }, [
    transparency,
    compatibility,
    showAssembly,
    assembly,
  ]);

  // --- Design config updates (no engine/scene recreation) ---
  useEffect(() => {
    const cover = coverRef.current;
    const brand = brandingRef.current;
    const design = designRef.current;
    if (cover && cover.update) try { cover.update(designConfig || {}); } catch (_) {}
    if (brand && brand.update) try { brand.update(designConfig || {}); } catch (_) {}
    if (design && design.update) try { design.update(designConfig || {}); } catch (_) {}
  }, [designConfig]);

  // --- Ossiguard profile updates (no engine/scene recreation) ---
  useEffect(() => {
    const og = ossiguardRef.current;
    if (og && og.update) try { og.update(ossiguardProfile || {}); } catch (_) {}
  }, [ossiguardProfile]);

  const getContext = useCallback(() => ctxRef.current, []);
  const visibleLabels = useMemo(() => {
    const showStation =
      display.measurements !== false &&
      (mode === 'internal' || mode === 'measure');

    const showDim =
      display.measurements !== false &&
      mode === 'measure';

    const showWarning =
      mode === 'cover' ||
      mode === 'fit';

    return labels.filter((label) => {
      const kind = label.kind || 'part';

      if (
        compatibility &&
        [
          'warning',
          'safety-warning',
          'station',
          'dim',
          'access',
          'keepout',
          'sensitive',
          'movement',
        ].includes(kind)
      ) {
        return false;
      }

      if (kind === 'warning') {
        return showWarning;
      }

      if (kind === 'safety-warning') {
        return true;
      }

      if (kind === 'station') {
        return showStation;
      }

      if (kind === 'dim') {
        return showDim;
      }

      if (kind === 'access') {
        return display.access !== false &&
          (showAllLabels || label.id === selectedId);
      }

      if (kind === 'keepout') {
        return display.keepOut !== false &&
          (showAllLabels || label.id === selectedId);
      }

      if (kind === 'sensitive') {
        return display.sensitive !== false &&
          (showAllLabels || label.id === selectedId);
      }

      if (kind === 'movement') {
        return display.movement !== false &&
          (showAllLabels || label.id === selectedId);
      }

      if (showAllLabels) {
        return true;
      }

      return !!selectedId &&
        (
          label.id === selectedId ||
          label.id === `part-${selectedId}`
        );
    });
  }, [
    labels,
    compatibility,
    mode,
    showAllLabels,
    selectedId,
    display,
  ]);

  const handleRetry = () => {
    setEngineError(null);
    setAttempt((a) => a + 1);
  };

  // --- Fatal engine overlay ---
  if (engineError) {
    const support = probeWebGLSupport();

    const webgl = [
      `WebGL2: ${support.webgl2 ? 'Available' : 'Unavailable'}`,
      `WebGL1: ${support.webgl1 ? 'Available' : 'Unavailable'}`,
    ].join(' · ');

    const canvas = canvasRef.current;
    return (
      <div className="flex h-full w-full items-center justify-center p-6">
        <div className="panel max-w-lg space-y-3 p-6">
          <div className="flex items-center gap-2 text-red-300"><ShieldAlert className="h-5 w-5" /><span className="text-sm font-semibold">Babylon Engine could not initialise</span></div>
          <p className="text-xs text-slate-400">The fatal viewport message is shown only when the Engine itself cannot start. Optional-layer failures never reach this state.</p>
          <dl className="divide-y divide-white/5 rounded-lg border border-white/10 bg-black/20 text-xs">
            {[
              ['Actual error', engineError],
              ['Canvas state', canvas ? (canvas.isConnected ? 'connected' : 'detached') : 'no canvas ref'],
              ['Canvas dimensions', canvas ? `${canvas.clientWidth}×${canvas.clientHeight}` : '—'],
              ['WebGL availability', webgl],
              ['Babylon version', BABYLON_VERSION],
              ['Browser renderer', typeof navigator !== 'undefined' ? navigator.userAgent : '—'],
            ].map(([k, v]) => (
              <div key={k} className="flex justify-between gap-3 px-3 py-2"><dt className="text-slate-500">{k}</dt><dd className="text-right text-slate-200">{String(v)}</dd></div>
            ))}
          </dl>
          <button onClick={handleRetry} className="btn-primary w-full"><RotateCcw className="mr-1.5 h-4 w-4" />Retry V2</button>
        </div>
      </div>
    );
  }

  const layerUnavailable = Object.entries(layerErrors).filter(([, v]) => v).map(([k]) => k);

  return (
    <div ref={containerRef} className="relative h-full w-full">
      <canvas ref={canvasRef} className="h-full w-full touch-none outline-none" />
      <DomLabelLayerV2 getContext={getContext} labels={visibleLabels} />

      {layerUnavailable.length > 0 && (
        <div className="absolute left-3 top-3 z-20 flex flex-wrap gap-1.5">
          {layerUnavailable.map((k) => (
            <span key={k} className="rounded-md border border-amber-400/40 bg-[#0b0f13]/90 px-2 py-1 text-[11px] font-medium text-amber-300">
              {labelName(k)} unavailable
            </span>
          ))}
        </div>
      )}

      <div className="pointer-events-none absolute bottom-3 left-1/2 z-20 -translate-x-1/2 rounded-lg border border-white/10 bg-[#0b0f13]/90 px-3 py-1.5 text-center text-[11px] text-slate-300 backdrop-blur">
        {designConfig ? (designConfig.custom_text_enabled ? 'Design concept applied — not manufacturing CAD' : 'Design styling applied — not manufacturing CAD') : (geometry && geometry.statusLabel ? geometry.statusLabel : 'Generic below-knee visual model — not customer geometry and not manufacturing CAD.')}
      </div>
    </div>
  );
}

function labelName(k) {
return { prosthesis: 'Prosthesis', stations: 'Measurement layer', cover: 'Cover layer', branding: 'Branding layer', design: 'Design layer', ossiguard: 'Ossiguard layer', workshopOverlay: 'Workshop overlays', assembly: 'Prosthesis Mapper assembly', workshopCover: 'Cover Builder preview' }[k] || k;
}