// asiz-photo.jsx — image primitives with motion
// - SmartImg: lazy-loaded, fades in when loaded, falls back to styled placeholder
// - KenBurns: slow zoom/pan on an image
// - Parallax: scroll-tied translateY on a wrapped child
// - MaskReveal: image paints in from one edge on scroll
// - BeforeAfter: draggable scrubber between two images

function useScrollContainer(ref) {
  // Find the scrollable ancestor so we can listen to the right scroll events
  const [container, setContainer] = React.useState(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let p = el.parentElement;
    while (p) {
      const cs = getComputedStyle(p);
      if ((cs.overflowY === 'auto' || cs.overflowY === 'scroll') && p.scrollHeight > p.clientHeight) {
        setContainer(p);
        return;
      }
      p = p.parentElement;
    }
    setContainer(window);
  }, []);
  return container;
}

// Placeholder — striped, labeled, same proportions as final photo.
function Placeholder({ label, ratio = '5/4' }) {
  return (
    <div
      className="asiz-placeholder"
      style={{
        width: '100%',
        aspectRatio: ratio,
        position: 'absolute',
        inset: 0,
      }}
    >
      <span style={{ position: 'relative', zIndex: 1 }}>{label}</span>
    </div>
  );
}

function SmartImg({ src, alt = '', ratio = '5/4', style, className = '', objectPosition = 'center' }) {
  const [loaded, setLoaded] = React.useState(false);
  const [failed, setFailed] = React.useState(false);
  return (
    <div
      className={className}
      style={{
        position: 'relative',
        width: '100%',
        aspectRatio: ratio,
        overflow: 'hidden',
        background: 'var(--bg-2)',
        ...style,
      }}
    >
      {(!loaded || failed) && <Placeholder label={alt || 'photo'} ratio={ratio} />}
      {src && !failed && (
        <img
          src={src}
          alt={alt}
          onLoad={() => setLoaded(true)}
          onError={() => setFailed(true)}
          style={{
            width: '100%',
            height: '100%',
            objectFit: 'cover',
            objectPosition,
            opacity: loaded ? 1 : 0,
            transition: 'opacity .6s ease-out',
          }}
        />
      )}
    </div>
  );
}

// Ken Burns: slow zoom + optional pan, looping
function KenBurns({ src, alt = '', ratio = '5/4', from = { s: 1, x: 0, y: 0 }, to = { s: 1.12, x: -2, y: 2 }, duration = 18, style, rounded = 2 }) {
  const keyId = React.useId().replace(/[:]/g, '');
  const styleTag = `
    @keyframes kb-${keyId} {
      0% { transform: scale(${from.s}) translate(${from.x}%, ${from.y}%); }
      100% { transform: scale(${to.s}) translate(${to.x}%, ${to.y}%); }
    }
  `;
  return (
    <div style={{
      position: 'relative',
      width: '100%',
      aspectRatio: ratio,
      overflow: 'hidden',
      borderRadius: rounded,
      background: 'var(--bg-2)',
      ...style,
    }}>
      <style>{styleTag}</style>
      <div style={{
        position: 'absolute', inset: 0,
        animation: `kb-${keyId} ${duration}s ease-in-out infinite alternate`,
      }}>
        <SmartImg src={src} alt={alt} ratio={ratio} style={{ aspectRatio: 'auto', height: '100%' }} />
      </div>
    </div>
  );
}

// Parallax: translateY proportional to how far the element is through the viewport
function Parallax({ children, strength = 0.2, style, className }) {
  const wrapRef = React.useRef(null);
  const innerRef = React.useRef(null);
  const container = useScrollContainer(wrapRef);
  React.useEffect(() => {
    if (!container) return;
    const scrollTarget = container === window ? window : container;
    const compute = () => {
      const el = wrapRef.current;
      const inner = innerRef.current;
      if (!el || !inner) return;
      const cRect = container === window
        ? { top: 0, height: window.innerHeight }
        : container.getBoundingClientRect();
      const eRect = el.getBoundingClientRect();
      const center = (eRect.top - cRect.top) + eRect.height / 2;
      const viewportCenter = cRect.height / 2;
      const delta = center - viewportCenter;
      inner.style.transform = `translate3d(0, ${delta * -strength}px, 0)`;
    };
    compute();
    const onScroll = () => requestAnimationFrame(compute);
    scrollTarget.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll, { passive: true });
    return () => {
      scrollTarget.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, [container, strength]);
  return (
    <div ref={wrapRef} className={className} style={{ overflow: 'hidden', ...style }}>
      <div ref={innerRef} style={{ willChange: 'transform' }}>
        {children}
      </div>
    </div>
  );
}

// Mask reveal: image paints in from a side as it enters viewport
function MaskReveal({ src, alt, ratio = '5/4', direction = 'left', style }) {
  const [ref] = useInView();
  const clipByState = (inView, dir) => {
    if (inView) return 'inset(0 0 0 0)';
    switch (dir) {
      case 'left': return 'inset(0 100% 0 0)';
      case 'right': return 'inset(0 0 0 100%)';
      case 'top': return 'inset(0 0 100% 0)';
      case 'bottom': return 'inset(100% 0 0 0)';
      default: return 'inset(0 100% 0 0)';
    }
  };
  return (
    <div
      ref={ref}
      className="reveal"
      style={{
        position: 'relative',
        width: '100%',
        aspectRatio: ratio,
        overflow: 'hidden',
        clipPath: clipByState(false, direction),
        transition: 'clip-path 1.2s cubic-bezier(.7,0,.2,1), opacity .6s',
        opacity: 0,
        ...style,
      }}
    >
      <style>{`.reveal.is-in { clip-path: inset(0 0 0 0) !important; opacity: 1 !important; }`}</style>
      <SmartImg src={src} alt={alt} ratio={ratio} style={{ aspectRatio: 'auto', height: '100%' }} />
    </div>
  );
}

// Before/After scrubber
function BeforeAfter({ beforeSrc, afterSrc, ratio = '16/10' }) {
  const [pos, setPos] = React.useState(50);
  const ref = React.useRef(null);
  const dragging = React.useRef(false);

  const onMove = (e) => {
    if (!dragging.current || !ref.current) return;
    const r = ref.current.getBoundingClientRect();
    const x = (e.touches ? e.touches[0].clientX : e.clientX) - r.left;
    setPos(Math.max(0, Math.min(100, (x / r.width) * 100)));
  };
  const start = () => { dragging.current = true; };
  const end = () => { dragging.current = false; };

  React.useEffect(() => {
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', end);
    window.addEventListener('touchmove', onMove);
    window.addEventListener('touchend', end);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup', end);
      window.removeEventListener('touchmove', onMove);
      window.removeEventListener('touchend', end);
    };
  }, []);

  return (
    <div
      ref={ref}
      style={{
        position: 'relative',
        width: '100%',
        aspectRatio: ratio,
        overflow: 'hidden',
        background: 'var(--bg-2)',
        userSelect: 'none',
        cursor: 'ew-resize',
      }}
      onMouseDown={(e) => { start(); onMove(e); }}
      onTouchStart={(e) => { start(); onMove(e); }}
    >
      <SmartImg src={beforeSrc} alt="Before" ratio={ratio} style={{ position: 'absolute', inset: 0, aspectRatio: 'auto', height: '100%' }} />
      <div style={{ position: 'absolute', inset: 0, clipPath: `inset(0 ${100 - pos}% 0 0)` }}>
        <SmartImg src={afterSrc} alt="After" ratio={ratio} style={{ aspectRatio: 'auto', height: '100%' }} />
      </div>
      {/* labels */}
      <span style={{ position: 'absolute', top: 14, left: 14, fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--bg)', background: 'rgba(0,0,0,0.4)', padding: '4px 8px', borderRadius: 2 }}>Before</span>
      <span style={{ position: 'absolute', top: 14, right: 14, fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--ink)', background: 'color-mix(in oklab, var(--bg) 90%, transparent)', padding: '4px 8px', borderRadius: 2 }}>After</span>
      {/* divider + handle */}
      <div style={{ position: 'absolute', top: 0, bottom: 0, left: `${pos}%`, width: 2, background: 'var(--bg)', transform: 'translateX(-1px)' }} />
      <div style={{
        position: 'absolute', top: '50%', left: `${pos}%`,
        transform: 'translate(-50%, -50%)',
        width: 44, height: 44, borderRadius: 999,
        background: 'var(--bg)', color: 'var(--ink)',
        display: 'grid', placeItems: 'center',
        boxShadow: '0 4px 14px rgba(0,0,0,0.25)',
        fontSize: 16,
      }}>⇄</div>
    </div>
  );
}

Object.assign(window, { SmartImg, KenBurns, Parallax, MaskReveal, BeforeAfter, HeroVideo });

// Video hero with slow Ken-Burns-style scale + bottom-right watermark mask
function HeroVideo({ src, ratio = '5/4', rounded = 2, style, maskColor, showMask = true, poster }) {
  const vRef = React.useRef(null);
  const [needsTap, setNeedsTap] = React.useState(false);

  const tryPlay = React.useCallback(() => {
    const v = vRef.current;
    if (!v) return;
    v.muted = true; v.defaultMuted = true; v.volume = 0;
    const p = v.play();
    if (p && p.then) {
      p.then(() => setNeedsTap(false)).catch(() => setNeedsTap(true));
    }
  }, []);

  React.useEffect(() => {
    const v = vRef.current;
    if (!v) return;
    v.muted = true; v.defaultMuted = true; v.volume = 0; v.playsInline = true; v.loop = true;
    v.setAttribute('muted', '');
    v.setAttribute('playsinline', '');
    v.setAttribute('webkit-playsinline', '');
    tryPlay();
    // Retry on visibility / first user gesture anywhere on the page
    const onGesture = () => { tryPlay(); };
    window.addEventListener('touchstart', onGesture, { once: true, passive: true });
    window.addEventListener('click', onGesture, { once: true });
    document.addEventListener('visibilitychange', tryPlay);
    return () => {
      window.removeEventListener('touchstart', onGesture);
      window.removeEventListener('click', onGesture);
      document.removeEventListener('visibilitychange', tryPlay);
    };
  }, [tryPlay]);

  return (
    <div style={{
      position: 'relative', width: '100%', aspectRatio: ratio,
      overflow: 'hidden', borderRadius: rounded,
      background: 'var(--bg-2)', ...style,
    }}>
      <video
        ref={vRef}
        src={src}
        muted
        defaultMuted
        playsInline
        webkit-playsinline="true"
        autoPlay
        loop
        preload="metadata"
        poster={poster}
        style={{
          width: '100%', height: '100%', objectFit: 'cover',
          display: 'block',
          animation: 'kb-video 22s ease-in-out infinite alternate',
        }}
      />
      {needsTap && (
        <button
          onClick={tryPlay}
          aria-label="Play video"
          style={{
            position: 'absolute', inset: 0,
            display: 'grid', placeItems: 'center',
            background: 'rgba(0,0,0,0.15)',
            border: 0, cursor: 'pointer',
            color: 'white',
          }}
        >
          <span style={{
            width: 64, height: 64, borderRadius: 999,
            background: 'rgba(255,255,255,0.92)', color: '#1a1a1a',
            display: 'grid', placeItems: 'center',
            fontSize: 22, paddingLeft: 4,
            boxShadow: '0 8px 30px rgba(0,0,0,0.35)',
          }}>▶</span>
        </button>
      )}
      <style>{`
        @keyframes kb-video {
          0% { transform: scale(1.02) translate(0.5%, 0.5%); }
          100% { transform: scale(1.12) translate(-1.5%, -1.5%); }
        }
      `}</style>
      {showMask && (
        <>
          {/* Bottom-right watermark mask — soft gradient box matching frame edges */}
          <div aria-hidden="true" style={{
            position: 'absolute',
            right: 0, bottom: 0,
            width: '22%', height: '14%',
            background: `linear-gradient(
              135deg,
              transparent 0%,
              ${maskColor || 'rgba(60,46,34,0.88)'} 32%,
              ${maskColor || 'rgba(60,46,34,0.96)'} 100%
            )`,
            pointerEvents: 'none',
          }} />
          {/* Subtle vignette on the masked corner so it blends */}
          <div aria-hidden="true" style={{
            position: 'absolute',
            right: 0, bottom: 0,
            width: '26%', height: '18%',
            background: 'radial-gradient(ellipse at bottom right, rgba(0,0,0,0.35), transparent 70%)',
            pointerEvents: 'none',
          }} />
        </>
      )}
    </div>
  );
}
