// ==========================================================================
// Tweaks app — mounts <TweaksPanel> with a suite of knobs for the survey.
// Lives in its own React root; does NOT touch survey.app.jsx.
// All state lives in CSS variables on :root and on window.__llBgConfig.
// ==========================================================================

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "bgSpeed": 2,
  "bgPaused": false,
  "bgPausedAt": 0,
  "bgAutoplay": 0,
  "bgReverse": false,
  "bgInsetTop": 24,
  "bgInsetSide": 24,
  "bgRadius": 6,
  "bgZoom": 1.0,
  "bgShiftY": 0,
  "bgVignette": 0.18,
  "bgBlur": 0,
  "bgSaturate": 1.0,
  "bgBrightness": 1.0,
  "bgTintStrength": 0,
  "bgTint": "#B8893B",

  "glassBlur": 18,
  "glassSaturate": 1.6,
  "glassOpacity": 0.92,
  "glassTint": "#FFFFFF",
  "glassEmboss": 1.0,
  "glassDisplacement": 0.85,
  "glassDisplacementScale": 1.0,
  "glassShadow": 1.0,
  "glassRadius": 6,
  "glassRim": 0.45,
  "glassRimColor": "white",

  "sceneGap": 28,
  "scenePadY": 44,
  "scenePadX": 28,

  "fadeDistance": 80,
  "fadeDuration": 700,
  "fadeStagger": 80,
  "fadeEnabled": true,

  "frameShadow": 1.0,
  "pageBg": "#0E0B07",

  "parallaxStrength": 0,
  "tiltEnabled": false,
  "tiltStrength": 6,

  "cursorSpotlight": false,
  "spotlightRadius": 280,

  "shimmerEnabled": false,
  "preset": "default"
}/*EDITMODE-END*/;

// ── Color helpers ───────────────────────────────────────────────────────────
function hexToRgb(hex) {
  const m = String(hex || '').replace('#', '').match(/^([0-9a-f]{3}|[0-9a-f]{6})$/i);
  if (!m) return [255, 255, 255];
  let h = m[1];
  if (h.length === 3) h = h.split('').map(c => c + c).join('');
  const n = parseInt(h, 16);
  return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
}

// ── CSS variable setter ─────────────────────────────────────────────────────
function setVar(name, value) {
  document.documentElement.style.setProperty(name, value);
}

// ── Apply tweaks → CSS vars + window globals ────────────────────────────────
function applyTweaks(t) {
  // Background frame
  setVar('--bg-inset-top', `${t.bgInsetTop}px`);
  setVar('--bg-inset-side', `${t.bgInsetSide}px`);
  setVar('--bg-radius', `${t.bgRadius}px`);
  setVar('--bg-zoom', t.bgZoom);
  setVar('--bg-shift-y', `${t.bgShiftY}px`);
  setVar('--bg-vignette', t.bgVignette);
  setVar('--bg-blur', `${t.bgBlur}px`);
  setVar('--bg-saturate', t.bgSaturate);
  setVar('--bg-brightness', t.bgBrightness);
  setVar('--bg-tint-strength', t.bgTintStrength);
  const [tr, tg, tb] = hexToRgb(t.bgTint);
  setVar('--bg-tint-r', tr);
  setVar('--bg-tint-g', tg);
  setVar('--bg-tint-b', tb);

  // Glass
  setVar('--glass-blur', `${t.glassBlur}px`);
  setVar('--glass-saturate', t.glassSaturate);
  setVar('--glass-opacity', t.glassOpacity);
  const [gr, gg, gb] = hexToRgb(t.glassTint);
  setVar('--glass-tint-r', gr);
  setVar('--glass-tint-g', gg);
  setVar('--glass-tint-b', gb);
  setVar('--glass-emboss', t.glassEmboss);
  setVar('--glass-displacement', t.glassDisplacement);
  setVar('--glass-displacement-scale', t.glassDisplacementScale);
  setVar('--glass-shadow', t.glassShadow);
  setVar('--glass-radius', `${t.glassRadius}px`);
  setVar('--glass-rim', t.glassRim);
  setVar('--glass-gold-rim', t.glassRimColor === 'gold' ? t.glassRim : 0);
  document.body.setAttribute('data-rim', t.glassRimColor);

  // Scene spacing
  setVar('--scene-gap', `${t.sceneGap}px`);
  setVar('--scene-pad-y', `${t.scenePadY}px`);
  setVar('--scene-pad-x', `${t.scenePadX}px`);

  // Fade
  setVar('--fade-distance', `${t.fadeEnabled ? t.fadeDistance : 0}px`);
  setVar('--fade-duration', `${t.fadeDuration}ms`);
  document.body.setAttribute('data-fade', t.fadeEnabled ? 'on' : 'off');

  // Frame shadow + page bg
  setVar('--frame-shadow', t.frameShadow);
  setVar('--page-bg', t.pageBg);

  // BG runtime config
  if (window.__llBgConfig) {
    window.__llBgConfig.speed = t.bgSpeed;
    window.__llBgConfig.paused = !!t.bgPaused;
    window.__llBgConfig.pausedAt = t.bgPausedAt;
    window.__llBgConfig.autoplay = t.bgAutoplay;
    window.__llBgConfig.direction = t.bgReverse ? -1 : 1;
    if (window.__llBgUpdate) window.__llBgUpdate();
    if (t.bgAutoplay > 0 && window.__llBgStartAutoplay) window.__llBgStartAutoplay();
  }

  // Toggle features
  document.body.classList.toggle('twk-tilt', !!t.tiltEnabled);
  document.body.dataset.tiltStrength = t.tiltStrength;
  document.body.classList.toggle('twk-spotlight', !!t.cursorSpotlight);
  setVar('--spotlight-radius', `${t.spotlightRadius}px`);
  document.body.classList.toggle('twk-shimmer', !!t.shimmerEnabled);

  // Parallax handled in observer below
  window.__llParallaxStrength = t.parallaxStrength;
  document.body.classList.toggle('twk-parallax', t.parallaxStrength > 0);
  window.__llFadeStagger = t.fadeStagger;
}

// ── Scene reveal observer (one-shot) + stagger ─────────────────────────────
function setupReveal() {
  const seen = new WeakSet();
  function attach() {
    const els = document.querySelectorAll('section.scene');
    if (!els.length) return false;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !seen.has(e.target)) {
          seen.add(e.target);
          const stagger = Math.max(0, window.__llFadeStagger || 0);
          // Use index of intersecting siblings for stagger
          const sibs = [...e.target.parentElement.querySelectorAll('section.scene')];
          const i = sibs.indexOf(e.target);
          e.target.style.transitionDelay = stagger ? `${(i % 4) * stagger}ms` : '0ms';
          requestAnimationFrame(() => e.target.classList.add('is-visible'));
        }
      });
    }, { threshold: 0.08, rootMargin: '0px 0px -8% 0px' });
    els.forEach((el) => io.observe(el));
    return true;
  }
  let tries = 0;
  (function tick() {
    if (attach()) return;
    if (++tries < 60) setTimeout(tick, 200);
  })();
}

// ── Parallax (light translateY on scenes based on viewport position) ────────
function setupParallax() {
  let raf = null;
  function update() {
    raf = null;
    const strength = window.__llParallaxStrength || 0;
    if (!strength) {
      document.querySelectorAll('section.scene').forEach((el) => {
        el.style.removeProperty('--parallax-y');
      });
      return;
    }
    const vh = window.innerHeight;
    document.querySelectorAll('section.scene').forEach((el) => {
      const r = el.getBoundingClientRect();
      const center = r.top + r.height / 2;
      const t = (center - vh / 2) / vh; // -1..1 around viewport center
      el.style.setProperty('--parallax-y', `${(-t * strength).toFixed(2)}px`);
    });
  }
  function onScroll() {
    if (raf == null) raf = requestAnimationFrame(update);
  }
  window.addEventListener('scroll', onScroll, { passive: true });
  window.addEventListener('resize', onScroll);
  setTimeout(update, 500);
}

// ── Tilt (mouse-follow 3D tilt on scenes) ───────────────────────────────────
function setupTilt() {
  document.addEventListener('mousemove', (e) => {
    if (!document.body.classList.contains('twk-tilt')) return;
    const strength = parseFloat(document.body.dataset.tiltStrength || '6');
    const w = window.innerWidth, h = window.innerHeight;
    const px = (e.clientX / w - 0.5) * 2; // -1..1
    const py = (e.clientY / h - 0.5) * 2;
    document.documentElement.style.setProperty('--tilt-x', `${(-py * strength).toFixed(2)}deg`);
    document.documentElement.style.setProperty('--tilt-y', `${(px * strength).toFixed(2)}deg`);
  });
}

// ── Cursor spotlight ────────────────────────────────────────────────────────
function setupSpotlight() {
  document.addEventListener('mousemove', (e) => {
    if (!document.body.classList.contains('twk-spotlight')) return;
    document.documentElement.style.setProperty('--spotlight-x', `${e.clientX}px`);
    document.documentElement.style.setProperty('--spotlight-y', `${e.clientY}px`);
  });
}

// ── Inject extra CSS (parallax/tilt/spotlight/shimmer) ──────────────────────
function injectExtraCSS() {
  if (document.getElementById('twk-extra-css')) return;
  const style = document.createElement('style');
  style.id = 'twk-extra-css';
  style.textContent = `
    section.scene {
      --parallax-y: 0px;
      --tilt-x: 0deg;
      --tilt-y: 0deg;
    }
    /* Parallax + tilt only when those modes are explicitly enabled.
       Applying transform here breaks position:sticky on descendants
       (e.g. .bucket-bar) — so we gate it behind body classes the user
       has to opt into via the Tweaks panel. */
    body.twk-parallax section.scene.is-visible,
    body.twk-tilt section.scene.is-visible {
      transform: translateY(var(--parallax-y, 0px)) perspective(1200px)
                 rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
    }
    body.twk-tilt section.scene {
      transition: transform 220ms cubic-bezier(.2,.7,.2,1),
                  opacity var(--fade-duration) var(--fade-ease),
                  backdrop-filter 220ms ease, background 220ms ease, border-color 220ms ease, box-shadow 220ms ease;
    }

    /* Cursor spotlight: warm radial glow follows mouse */
    body.twk-spotlight::before {
      content: "";
      position: fixed; inset: 0;
      pointer-events: none; z-index: 9998;
      background: radial-gradient(
        circle var(--spotlight-radius, 280px) at var(--spotlight-x, 50%) var(--spotlight-y, 50%),
        rgba(255, 220, 160, 0.18),
        transparent 70%
      );
      mix-blend-mode: screen;
      transition: background 60ms linear;
    }

    /* Shimmer mode: animated sheen on every scene */
    body.twk-shimmer section.scene::before {
      background:
        radial-gradient(ellipse 70% 45% at 22% -8%, rgba(255,255,255, calc(0.55 * var(--glass-emboss))), transparent 55%),
        radial-gradient(ellipse 120% 35% at 50% 0%, rgba(255,255,255, calc(0.18 * var(--glass-emboss))), transparent 65%),
        linear-gradient(180deg, transparent 78%, rgba(20,15,8, calc(0.10 * var(--glass-emboss))) 100%),
        linear-gradient(115deg, transparent 30%, rgba(255,255,255,0.18) 50%, transparent 70%);
      background-size: 100% 100%, 100% 100%, 100% 100%, 250% 100%;
      background-position: 0 0, 0 0, 0 0, 0 0;
      animation: twk-shimmer-sweep 6s linear infinite;
    }
    @keyframes twk-shimmer-sweep {
      0%   { background-position: 0 0, 0 0, 0 0, 200% 0; }
      100% { background-position: 0 0, 0 0, 0 0, -50% 0; }
    }

    /* Fade off → no transform on scenes */
    body[data-fade="off"] section.scene {
      opacity: 1 !important;
      transform: none !important;
    }
  `;
  document.head.appendChild(style);
}

// ── Presets ─────────────────────────────────────────────────────────────────
const PRESETS = {
  default: { ...TWEAK_DEFAULTS },
  cinematic: {
    bgVignette: 0.45, bgSaturate: 1.2, bgBrightness: 0.9, bgZoom: 1.08,
    glassOpacity: 0.32, glassEmboss: 1.3, glassDisplacement: 0.6, glassShadow: 1.5,
    fadeDistance: 120, fadeDuration: 1000, fadeStagger: 120,
  },
  airy: {
    bgVignette: 0.05, bgSaturate: 0.95, bgBrightness: 1.1, bgBlur: 4,
    glassOpacity: 0.55, glassBlur: 28, glassEmboss: 0.6, glassDisplacement: 0.3,
    glassShadow: 0.7, glassRadius: 16,
  },
  brutal: {
    bgVignette: 0.5, bgSaturate: 1.4, bgBrightness: 0.85,
    glassOpacity: 0.15, glassBlur: 6, glassEmboss: 2.0, glassDisplacement: 1.0,
    glassShadow: 2.0, glassRadius: 0, glassRim: 0.8,
  },
  goldRush: {
    bgTintStrength: 0.45, bgTint: "#B8893B", bgSaturate: 1.3,
    glassRimColor: "gold", glassRim: 0.7, glassEmboss: 1.4,
  },
  glasshouse: {
    glassOpacity: 0.18, glassBlur: 32, glassSaturate: 2.0,
    glassEmboss: 1.6, glassDisplacement: 1.0, glassDisplacementScale: 1.5,
    glassShadow: 1.4,
  },
  paper: {
    bgBlur: 12, bgSaturate: 0.6, bgBrightness: 1.05,
    glassOpacity: 0.7, glassBlur: 8, glassEmboss: 0.4, glassDisplacement: 0.2,
    glassRim: 0.2,
  },
  parallaxFun: {
    parallaxStrength: 30, tiltEnabled: true, tiltStrength: 4,
    fadeDistance: 100, fadeStagger: 60,
  },
  midnight: {
    bgBrightness: 0.55, bgSaturate: 0.9, bgVignette: 0.6,
    glassOpacity: 0.25, glassTint: "#0A0808", glassEmboss: 1.5,
    glassRim: 0.15, pageBg: "#000000",
  },
};

// ── React app ───────────────────────────────────────────────────────────────
function TweaksApp() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  React.useEffect(() => {
    applyTweaks(t);
  }, [t]);

  const applyPreset = (name) => {
    const p = PRESETS[name];
    if (!p) return;
    const next = { ...TWEAK_DEFAULTS, ...p, preset: name };
    setTweak(next);
  };

  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Presets" />
      <TweakSelect label="Vibe" value={t.preset}
        options={[
          { value: 'default', label: 'Default' },
          { value: 'cinematic', label: 'Cinematic' },
          { value: 'airy', label: 'Airy' },
          { value: 'brutal', label: 'Brutalist' },
          { value: 'goldRush', label: 'Gold Rush' },
          { value: 'glasshouse', label: 'Glasshouse' },
          { value: 'paper', label: 'Paper' },
          { value: 'parallaxFun', label: 'Parallax Fun' },
          { value: 'midnight', label: 'Midnight' },
        ]}
        onChange={applyPreset} />

      <TweakSection label="Background video" />
      <TweakSlider label="Scroll speed (loops/page)" value={t.bgSpeed}
        min={0.25} max={8} step={0.25} unit="×"
        onChange={(v) => setTweak('bgSpeed', v)} />
      <TweakToggle label="Reverse direction" value={t.bgReverse}
        onChange={(v) => setTweak('bgReverse', v)} />
      <TweakToggle label="Pause on scroll" value={t.bgPaused}
        onChange={(v) => setTweak('bgPaused', v)} />
      {t.bgPaused && (
        <TweakSlider label="Paused frame" value={t.bgPausedAt}
          min={0} max={358} step={1}
          onChange={(v) => setTweak('bgPausedAt', v)} />
      )}
      <TweakSlider label="Auto-play (fps)" value={t.bgAutoplay}
        min={0} max={60} step={1} unit=" fps"
        onChange={(v) => setTweak('bgAutoplay', v)} />

      <TweakSection label="Background frame & sizing" />
      <TweakSlider label="Inset (top)" value={t.bgInsetTop}
        min={0} max={120} step={2} unit="px"
        onChange={(v) => setTweak('bgInsetTop', v)} />
      <TweakSlider label="Inset (sides)" value={t.bgInsetSide}
        min={0} max={120} step={2} unit="px"
        onChange={(v) => setTweak('bgInsetSide', v)} />
      <TweakSlider label="Frame radius" value={t.bgRadius}
        min={0} max={40} step={1} unit="px"
        onChange={(v) => setTweak('bgRadius', v)} />
      <TweakSlider label="Zoom" value={t.bgZoom}
        min={0.5} max={2.0} step={0.05} unit="×"
        onChange={(v) => setTweak('bgZoom', v)} />
      <TweakSlider label="Vertical shift" value={t.bgShiftY}
        min={-200} max={200} step={4} unit="px"
        onChange={(v) => setTweak('bgShiftY', v)} />
      <TweakSlider label="Frame shadow" value={t.frameShadow}
        min={0} max={2.5} step={0.05} unit="×"
        onChange={(v) => setTweak('frameShadow', v)} />

      <TweakSection label="Background look" />
      <TweakSlider label="Vignette" value={t.bgVignette}
        min={0} max={0.8} step={0.02}
        onChange={(v) => setTweak('bgVignette', v)} />
      <TweakSlider label="Blur" value={t.bgBlur}
        min={0} max={30} step={1} unit="px"
        onChange={(v) => setTweak('bgBlur', v)} />
      <TweakSlider label="Saturation" value={t.bgSaturate}
        min={0} max={2.5} step={0.05} unit="×"
        onChange={(v) => setTweak('bgSaturate', v)} />
      <TweakSlider label="Brightness" value={t.bgBrightness}
        min={0.3} max={1.8} step={0.05} unit="×"
        onChange={(v) => setTweak('bgBrightness', v)} />
      <TweakColor label="Tint color" value={t.bgTint}
        onChange={(v) => setTweak('bgTint', v)} />
      <TweakSlider label="Tint strength" value={t.bgTintStrength}
        min={0} max={1} step={0.02}
        onChange={(v) => setTweak('bgTintStrength', v)} />
      <TweakColor label="Page background" value={t.pageBg}
        onChange={(v) => setTweak('pageBg', v)} />

      <TweakSection label="Glass: emboss & material" />
      <TweakSlider label="Emboss strength" value={t.glassEmboss}
        min={0} max={2.5} step={0.05} unit="×"
        onChange={(v) => setTweak('glassEmboss', v)} />
      <TweakSlider label="Displacement opacity" value={t.glassDisplacement}
        min={0} max={1.5} step={0.02}
        onChange={(v) => setTweak('glassDisplacement', v)} />
      <TweakSlider label="Displacement scale" value={t.glassDisplacementScale}
        min={0.4} max={3} step={0.05} unit="×"
        onChange={(v) => setTweak('glassDisplacementScale', v)} />
      <TweakSlider label="Drop shadow" value={t.glassShadow}
        min={0} max={2.5} step={0.05} unit="×"
        onChange={(v) => setTweak('glassShadow', v)} />

      <TweakSection label="Glass: frost & opacity" />
      <TweakSlider label="Backdrop blur" value={t.glassBlur}
        min={0} max={48} step={1} unit="px"
        onChange={(v) => setTweak('glassBlur', v)} />
      <TweakSlider label="Backdrop saturation" value={t.glassSaturate}
        min={0.5} max={3} step={0.05} unit="×"
        onChange={(v) => setTweak('glassSaturate', v)} />
      <TweakSlider label="Glass opacity" value={t.glassOpacity}
        min={0} max={1} step={0.02}
        onChange={(v) => setTweak('glassOpacity', v)} />
      <TweakColor label="Glass tint" value={t.glassTint}
        onChange={(v) => setTweak('glassTint', v)} />
      <TweakSlider label="Corner radius" value={t.glassRadius}
        min={0} max={40} step={1} unit="px"
        onChange={(v) => setTweak('glassRadius', v)} />
      <TweakSlider label="Border opacity" value={t.glassRim}
        min={0} max={1} step={0.02}
        onChange={(v) => setTweak('glassRim', v)} />
      <TweakRadio label="Border color" value={t.glassRimColor}
        options={['white', 'gold']}
        onChange={(v) => setTweak('glassRimColor', v)} />

      <TweakSection label="Section spacing" />
      <TweakSlider label="Gap between" value={t.sceneGap}
        min={0} max={120} step={2} unit="px"
        onChange={(v) => setTweak('sceneGap', v)} />
      <TweakSlider label="Padding (vert)" value={t.scenePadY}
        min={16} max={120} step={2} unit="px"
        onChange={(v) => setTweak('scenePadY', v)} />
      <TweakSlider label="Padding (horiz)" value={t.scenePadX}
        min={12} max={80} step={2} unit="px"
        onChange={(v) => setTweak('scenePadX', v)} />

      <TweakSection label="Entrance animation" />
      <TweakToggle label="Fade in on scroll" value={t.fadeEnabled}
        onChange={(v) => setTweak('fadeEnabled', v)} />
      <TweakSlider label="Rise distance" value={t.fadeDistance}
        min={0} max={240} step={4} unit="px"
        onChange={(v) => setTweak('fadeDistance', v)} />
      <TweakSlider label="Duration" value={t.fadeDuration}
        min={150} max={2000} step={50} unit="ms"
        onChange={(v) => setTweak('fadeDuration', v)} />
      <TweakSlider label="Stagger (per child)" value={t.fadeStagger}
        min={0} max={300} step={10} unit="ms"
        onChange={(v) => setTweak('fadeStagger', v)} />

      <TweakSection label="Motion FX" />
      <TweakSlider label="Parallax strength" value={t.parallaxStrength}
        min={0} max={80} step={1} unit="px"
        onChange={(v) => setTweak('parallaxStrength', v)} />
      <TweakToggle label="3D tilt on cursor" value={t.tiltEnabled}
        onChange={(v) => setTweak('tiltEnabled', v)} />
      {t.tiltEnabled && (
        <TweakSlider label="Tilt strength" value={t.tiltStrength}
          min={1} max={20} step={1} unit="°"
          onChange={(v) => setTweak('tiltStrength', v)} />
      )}
      <TweakToggle label="Cursor spotlight" value={t.cursorSpotlight}
        onChange={(v) => setTweak('cursorSpotlight', v)} />
      {t.cursorSpotlight && (
        <TweakSlider label="Spotlight radius" value={t.spotlightRadius}
          min={120} max={600} step={20} unit="px"
          onChange={(v) => setTweak('spotlightRadius', v)} />
      )}
      <TweakToggle label="Shimmer sweep on glass" value={t.shimmerEnabled}
        onChange={(v) => setTweak('shimmerEnabled', v)} />

      <TweakSection label="Quick actions" />
      <TweakButton label="Scroll to top"
        onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} />
      <TweakButton label="Reset to defaults"
        onClick={() => setTweak({ ...TWEAK_DEFAULTS })} />
    </TweaksPanel>
  );
}

// ── Mount ───────────────────────────────────────────────────────────────────
(function init() {
  injectExtraCSS();
  setupReveal();
  setupParallax();
  setupTilt();
  setupSpotlight();

  const mount = document.createElement('div');
  mount.id = 'tweaks-root';
  document.body.appendChild(mount);
  ReactDOM.createRoot(mount).render(<TweaksApp />);
})();
