// ethereal-shadow.jsx — Ported from etheral-shadow.tsx (TypeScript → vanilla JS)
// framer-motion animate/useMotionValue → GSAP tween with onUpdate
// GSAP already loaded as CDN global.

// ─── Helpers ──────────────────────────────────────────────────────────────────
function mapRange(value, fromLow, fromHigh, toLow, toHigh) {
  if (fromLow === fromHigh) return toLow;
  return toLow + ((value - fromLow) / (fromHigh - fromLow)) * (toHigh - toLow);
}

let _shadowIdCounter = 0;
function uniqueShadowId() {
  return `shadowoverlay-${++_shadowIdCounter}`;
}

// ─── Component ────────────────────────────────────────────────────────────────
const EtherealShadow = ({
  sizing       = 'fill',
  color        = 'rgba(128, 128, 128, 1)',
  animation,          // { scale: number, speed: number }
  noise,              // { opacity: number, scale: number }
  style        = {},
  className    = '',
  heading      = 'Ethereal Shadows',
  showHeading  = true,
}) => {
  const idRef            = React.useRef(uniqueShadowId());
  const feColorMatrixRef = React.useRef(null);
  const tweenRef         = React.useRef(null);

  const animationEnabled = animation && animation.scale > 0;

  const displacementScale = animation
    ? mapRange(animation.scale, 1, 100, 20, 100) : 0;
  const animationDuration = animation
    ? mapRange(animation.speed, 1, 100, 1000, 50) / 25 : 1;

  React.useEffect(() => {
    if (!animationEnabled || !feColorMatrixRef.current) return;

    // Kill previous tween
    if (tweenRef.current) tweenRef.current.kill();

    const proxy = { val: 0 };
    tweenRef.current = gsap.to(proxy, {
      val: 360,
      duration: animationDuration,
      repeat: -1,
      ease: 'none',
      onUpdate() {
        if (feColorMatrixRef.current) {
          feColorMatrixRef.current.setAttribute('values', String(proxy.val));
        }
      },
    });

    return () => {
      if (tweenRef.current) tweenRef.current.kill();
    };
  }, [animationEnabled, animationDuration]);

  const id = idRef.current;
  const baseFreqX = animation ? mapRange(animation.scale, 0, 100, 0.001, 0.0005) : 0.001;
  const baseFreqY = animation ? mapRange(animation.scale, 0, 100, 0.004, 0.002) : 0.004;

  return (
    <div
      className={className}
      style={{
        overflow: 'hidden',
        position: 'relative',
        width: '100%',
        height: '100%',
        ...style,
      }}
    >
      {/* Distorted shadow layer */}
      <div style={{
        position: 'absolute',
        inset: -displacementScale,
        filter: animationEnabled ? `url(#${id}) blur(4px)` : 'none',
      }}>
        {animationEnabled && (
          <svg style={{ position: 'absolute', width: 0, height: 0 }}>
            <defs>
              <filter id={id}>
                <feTurbulence
                  result="undulation"
                  numOctaves="2"
                  baseFrequency={`${baseFreqX},${baseFreqY}`}
                  seed="0"
                  type="turbulence"
                />
                <feColorMatrix
                  ref={feColorMatrixRef}
                  in="undulation"
                  type="hueRotate"
                  values="180"
                />
                <feColorMatrix
                  in="dist"
                  result="circulation"
                  type="matrix"
                  values="4 0 0 0 1  4 0 0 0 1  4 0 0 0 1  1 0 0 0 0"
                />
                <feDisplacementMap
                  in="SourceGraphic"
                  in2="circulation"
                  scale={displacementScale}
                  result="dist"
                />
                <feDisplacementMap
                  in="dist"
                  in2="undulation"
                  scale={displacementScale}
                  result="output"
                />
              </filter>
            </defs>
          </svg>
        )}

        {/* Colour + mask */}
        <div style={{
          backgroundColor: color,
          maskImage: `url('https://framerusercontent.com/images/ceBGguIpUU8luwByxuQz79t7To.png')`,
          WebkitMaskImage: `url('https://framerusercontent.com/images/ceBGguIpUU8luwByxuQz79t7To.png')`,
          maskSize: sizing === 'stretch' ? '100% 100%' : 'cover',
          WebkitMaskSize: sizing === 'stretch' ? '100% 100%' : 'cover',
          maskRepeat: 'no-repeat',
          WebkitMaskRepeat: 'no-repeat',
          maskPosition: 'center',
          WebkitMaskPosition: 'center',
          width: '100%',
          height: '100%',
        }} />
      </div>

      {/* Optional centred heading */}
      {showHeading && (
        <div style={{
          position: 'absolute',
          top: '50%', left: '50%',
          transform: 'translate(-50%,-50%)',
          textAlign: 'center',
          zIndex: 10,
          width: '100%',
          pointerEvents: 'none',
        }}>
          <h2 style={{
            fontSize: 'clamp(3rem, 8vw, 6rem)',
            fontWeight: 700,
            textAlign: 'center',
            color: 'var(--text)',
            lineHeight: 1.1,
          }}>
            {heading}
          </h2>
        </div>
      )}

      {/* Film noise overlay */}
      {noise && noise.opacity > 0 && (
        <div style={{
          position: 'absolute',
          inset: 0,
          backgroundImage: `url('https://framerusercontent.com/images/g0QcWrxr87K0ufOxIUFBakwYA8.png')`,
          backgroundSize: noise.scale * 200,
          backgroundRepeat: 'repeat',
          opacity: noise.opacity / 2,
          pointerEvents: 'none',
        }} />
      )}
    </div>
  );
};

// ─── Demo wrapper ─────────────────────────────────────────────────────────────
const EtherealShadowDemo = () => (
  <div style={{ width: '100%', height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'var(--bg)' }}>
    <div style={{ width: '100%', height: '100%' }}>
      <EtherealShadow
        color="rgba(128, 128, 128, 1)"
        animation={{ scale: 100, speed: 90 }}
        noise={{ opacity: 1, scale: 1.2 }}
        sizing="fill"
      />
    </div>
  </div>
);

window.EtherealShadow     = EtherealShadow;
window.EtherealShadowDemo = EtherealShadowDemo;
