(function () {
  'use strict';

  if (window.__sixSevenRealisticHands && window.__sixSevenRealisticHands.ready) return;

  const MODEL_URL = chrome.runtime.getURL('assets/six-seven-overkill-hands.glb');
  const ANATOMICAL_MODEL_URL = chrome.runtime.getURL('assets/six-seven-open-empty-hand.glb');
  const CANVAS_ID = 'ss6-7-realistic-hands-canvas';
  const ACTIVE_CLASS = 'ss6-7-realistic-hands-on';
  const VARIANT_GROUPS = [
    ['6/7', '67'],
    ['6/seven', 'six/7', 'six/seven'],
    ['6 7', '6 seven', 'six 7', 'six seven'],
    ['6-7', '6-seven', 'six-7', 'six-seven'],
    ['6 - 7', '6 - seven', 'six - 7', 'six - seven'],
  ];
  const VARIANT_LIST = VARIANT_GROUPS.flat();
  const VARIANT_SET = new Set(VARIANT_LIST.map((variant) => normalize(variant).toLowerCase()));

  const MOTION_CONFIG = {
    paceMs: 385,
    bobPx: 16,
    driftPx: 8,
    wobblePaceMs: 2720,
    wobbleAmpDeg: 4.5,
    wobbleJoltPx: 0.4,
    tiltXDeg: 4,
    tiltSkewDeg: 1.5,
  };

  let canvas = null;
  let runtime = null;
  let runtimePromise = null;
  let animationFrame = 0;
  let queued = false;
  let activeRect = null;
  let activeVariant = '';

  function normalize(text) {
    return String(text || '')
      .replace(/\u00a0/g, ' ')
      .replace(/\s+/g, ' ')
      .trim();
  }

  function isSixSevenVariant(text) {
    const normalized = normalize(text);
    return normalized !== '' && VARIANT_SET.has(normalized.toLowerCase());
  }

  function ensureCanvas() {
    if (canvas && canvas.isConnected) return canvas;

    canvas = document.getElementById(CANVAS_ID);
    if (!canvas) {
      canvas = document.createElement('canvas');
      canvas.id = CANVAS_ID;
      canvas.setAttribute('aria-hidden', 'true');
      (document.documentElement || document.body).appendChild(canvas);
    }

    canvas.dataset.modelUrl = MODEL_URL;
    canvas.dataset.anatomicalModelUrl = ANATOMICAL_MODEL_URL;
    canvas.dataset.overkillMode = 'anatomical';
    canvas.dataset.overkillPropMode = 'center67';
    canvas.dataset.activation = 'selection-only';
    return canvas;
  }

  async function loadRuntime() {
    if (runtime) return runtime;
    if (!runtimePromise) {
      const url = chrome.runtime && chrome.runtime.getURL
        ? chrome.runtime.getURL('overkill3d.js')
        : './overkill3d.js';
      runtimePromise = import(url);
    }

    const module = await runtimePromise;
    runtime = module.createSixSevenOverkill(ensureCanvas(), {
      modelUrl: MODEL_URL,
      anatomicalModelUrl: ANATOMICAL_MODEL_URL,
      mode: 'anatomical',
      propMode: 'center67',
      motionConfig: MOTION_CONFIG,
    });
    window.addEventListener('resize', runtime.resize, { passive: true });
    return runtime;
  }

  function selectionRect(selection) {
    if (!selection || selection.rangeCount === 0) return null;

    let left = Infinity;
    let top = Infinity;
    let right = -Infinity;
    let bottom = -Infinity;

    for (let i = 0; i < selection.rangeCount; i += 1) {
      let range;
      try {
        range = selection.getRangeAt(i);
      } catch (_) {
        continue;
      }

      const rects = Array.from(range.getClientRects ? range.getClientRects() : []);
      if (rects.length === 0 && range.getBoundingClientRect) rects.push(range.getBoundingClientRect());

      for (const rect of rects) {
        if (!rect || rect.width <= 0 || rect.height <= 0) continue;
        left = Math.min(left, rect.left);
        top = Math.min(top, rect.top);
        right = Math.max(right, rect.right);
        bottom = Math.max(bottom, rect.bottom);
      }
    }

    if (!Number.isFinite(left) || !Number.isFinite(top) || right <= left || bottom <= top) return null;
    return { left, top, right, bottom, width: right - left, height: bottom - top };
  }

  function renderLoop(time) {
    animationFrame = 0;
    if (!activeRect || !runtime || !canvas || !canvas.classList.contains(ACTIVE_CLASS)) return;

    runtime.setMode('anatomical');
    runtime.setPropMode('center67');
    runtime.setMotionConfig(MOTION_CONFIG);
    canvas.dataset.selectedVariant = activeVariant || '6/7';
    runtime.setTargetRect(activeRect);
    runtime.resize();
    runtime.render(time);
    animationFrame = requestAnimationFrame(renderLoop);
  }

  function start(rect, variant) {
    activeRect = rect;
    activeVariant = variant;
    const targetCanvas = ensureCanvas();
    targetCanvas.dataset.selectedVariant = activeVariant;
    targetCanvas.classList.add(ACTIVE_CLASS);

    loadRuntime()
      .then((loadedRuntime) => {
        loadedRuntime.setMode('anatomical');
        loadedRuntime.setPropMode('center67');
        loadedRuntime.setMotionConfig(MOTION_CONFIG);
        targetCanvas.dataset.selectedVariant = activeVariant || '6/7';
        loadedRuntime.setTargetRect(activeRect);
        loadedRuntime.resize();
        if (!animationFrame) animationFrame = requestAnimationFrame(renderLoop);
      })
      .catch((error) => {
        targetCanvas.dataset.runtimeError = error && error.message ? error.message : String(error);
        stop();
      });
  }

  function stop() {
    activeRect = null;
    activeVariant = '';
    if (animationFrame) {
      cancelAnimationFrame(animationFrame);
      animationFrame = 0;
    }
    if (canvas) {
      canvas.classList.remove(ACTIVE_CLASS);
      delete canvas.dataset.selectedVariant;
    }
  }

  function updateFromSelection() {
    queued = false;
    const selection = window.getSelection && window.getSelection();
    if (!selection || selection.isCollapsed) {
      stop();
      return;
    }

    const selectedText = normalize(selection.toString());
    if (!isSixSevenVariant(selectedText)) {
      stop();
      return;
    }

    const rect = selectionRect(selection);
    if (!rect) {
      stop();
      return;
    }

    start(rect, selectedText);
  }

  function scheduleUpdate() {
    if (queued) return;
    queued = true;
    requestAnimationFrame(updateFromSelection);
  }

  document.addEventListener('selectionchange', scheduleUpdate);
  window.addEventListener('scroll', scheduleUpdate, { passive: true });
  window.addEventListener('pagehide', () => {
    stop();
    if (runtime) {
      window.removeEventListener('resize', runtime.resize);
      runtime.dispose();
      runtime = null;
    }
  });

  window.__sixSevenRealisticHands = {
    ready: true,
    isSixSevenVariant,
    getState() {
      return {
        active: Boolean(activeRect),
        selectedVariant: activeVariant,
        runtimeLoaded: Boolean(runtime),
        canvasVisible: Boolean(canvas && canvas.classList.contains(ACTIVE_CLASS)),
        mode: 'anatomical',
        propMode: 'center67',
      };
    },
  };
})();
