/* global React */
const { useState, useRef, useEffect, useCallback } = React;

/**
 * BeforeAfterSlider — Prompt Studio aesthetic
 * - Vertical drag handle (classic) by default
 * - Hover-to-reveal mode (handle follows cursor, no draggable knob)
 * - Horizontal mode (top/bottom reveal)
 * - Sharp corners, 1px hairline frame, yellow accent on the divider
 *
 * Props:
 *   before, after        : image URL or React node (placeholder)
 *   beforeLabel, afterLabel  : overlay labels (default Before / After)
 *   showLabels           : 'always' | 'hover' | 'never'
 *   mode                 : 'drag' | 'hover' | 'horizontal'
 *   aspectRatio          : CSS aspect-ratio string, default '16 / 10'
 *   containMode          : if true, use object-fit: contain (show native aspect ratios)
 *   onClick              : optional click handler (e.g. open lightbox)
 */
function BeforeAfterSlider({
  before,
  after,
  beforeLabel = 'Before',
  afterLabel = 'After',
  showLabels = 'hover',
  mode = 'drag',
  aspectRatio = '16 / 10',
  containMode = false,
  onClick,
  caption,
}) {
  const [pct, setPct] = useState(50);
  const [dragging, setDragging] = useState(false);
  const [hovered, setHovered] = useState(false);
  const frameRef = useRef(null);

  const updateFromEvent = useCallback((clientX, clientY) => {
    const el = frameRef.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    if (mode === 'horizontal') {
      const y = clientY - r.top;
      setPct(Math.max(0, Math.min(100, (y / r.height) * 100)));
    } else {
      const x = clientX - r.left;
      setPct(Math.max(0, Math.min(100, (x / r.width) * 100)));
    }
  }, [mode]);

  // Drag handlers
  useEffect(() => {
    if (!dragging) return;
    const onMove = (e) => {
      const t = e.touches ? e.touches[0] : e;
      updateFromEvent(t.clientX, t.clientY);
      e.preventDefault();
    };
    const onUp = () => setDragging(false);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
    window.addEventListener('touchmove', onMove, { passive: false });
    window.addEventListener('touchend', onUp);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup', onUp);
      window.removeEventListener('touchmove', onMove);
      window.removeEventListener('touchend', onUp);
    };
  }, [dragging, updateFromEvent]);

  const onMouseMove = (e) => {
    if (mode === 'hover') updateFromEvent(e.clientX, e.clientY);
  };

  const onMouseDown = (e) => {
    if (mode === 'hover') return;
    setDragging(true);
    const t = e.touches ? e.touches[0] : e;
    updateFromEvent(t.clientX, t.clientY);
  };

  // Reset to 50% when leaving in hover mode
  const onMouseLeave = () => {
    setHovered(false);
    if (mode === 'hover') setPct(50);
  };

  const isHorizontal = mode === 'horizontal';
  const labelsVisible =
    showLabels === 'always' || (showLabels === 'hover' && hovered);

  // Image/video rendering — supports placeholder objects { placeholder: true, ... }
  const renderLayer = (src, kind) => {
    if (!src) return null;
    
    // String path — check extension for video
    if (typeof src === 'string') {
      const isVideo = /\.(mp4|webm|mov)$/i.test(src);
      
      const objectFit = containMode ? 'contain' : 'cover';
      
      if (isVideo) {
        return (
          <video
            src={src}
            autoPlay
            loop
            muted
            playsInline
            style={{
              position: 'absolute',
              inset: 0,
              width: '100%',
              height: '100%',
              objectFit: objectFit,
              userSelect: 'none',
              pointerEvents: 'none',
            }}
          />
        );
      }
      
      return (
        <img
          src={src}
          alt={kind}
          draggable={false}
          style={{
            position: 'absolute',
            inset: 0,
            width: '100%',
            height: '100%',
            objectFit: objectFit,
            userSelect: 'none',
            pointerEvents: 'none',
          }}
        />
      );
    }
    
    // Custom node (e.g. placeholder)
    return (
      <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
        {src}
      </div>
    );
  };

  // Clip-path: AFTER is on top, clipped to reveal area
  // drag/hover (vertical divider): show AFTER from `pct` → 100%
  //   → polygon(pct% 0, 100% 0, 100% 100%, pct% 100%)
  // horizontal: show AFTER from `pct` → 100% (bottom)
  //   → polygon(0 pct%, 100% pct%, 100% 100%, 0 100%)
  const afterClip = isHorizontal
    ? `polygon(0 ${pct}%, 100% ${pct}%, 100% 100%, 0 100%)`
    : `polygon(${pct}% 0, 100% 0, 100% 100%, ${pct}% 100%)`;

  return (
    <div
      ref={frameRef}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={onMouseLeave}
      onMouseMove={onMouseMove}
      onMouseDown={onMouseDown}
      onTouchStart={onMouseDown}
      onClick={onClick}
      style={{
        position: 'relative',
        width: '100%',
        aspectRatio,
        overflow: 'hidden',
        background: containMode ? '#ffffff' : 'var(--prompt-light-gray)',
        border: '1px solid var(--prompt-black)',
        cursor:
          mode === 'hover'
            ? 'crosshair'
            : isHorizontal
            ? 'ns-resize'
            : 'ew-resize',
        userSelect: 'none',
        touchAction: 'none',
      }}
    >
      {/* BEFORE — full bleed underneath */}
      {renderLayer(before, 'before')}

      {/* AFTER — clipped */}
      <div
        style={{
          position: 'absolute',
          inset: 0,
          clipPath: afterClip,
          WebkitClipPath: afterClip,
          transition: dragging || mode === 'hover' ? 'none' : 'clip-path 200ms cubic-bezier(0.2,0.6,0.2,1)',
        }}
      >
        {renderLayer(after, 'after')}
      </div>

      {/* Labels */}
      <div
        style={{
          position: 'absolute',
          top: 16,
          left: 16,
          right: 16,
          display: 'flex',
          justifyContent: 'space-between',
          pointerEvents: 'none',
          opacity: labelsVisible ? 1 : 0,
          transition: 'opacity 200ms cubic-bezier(0.2,0.6,0.2,1)',
        }}
      >
        <span style={labelStyle('light')}>{beforeLabel}</span>
        <span style={labelStyle('dark')}>{afterLabel}</span>
      </div>

      {/* Caption (e.g. "Drag to compare") in bottom corner */}
      {caption && (
        <div
          style={{
            position: 'absolute',
            bottom: 14,
            left: 16,
            fontSize: 10,
            letterSpacing: '0.16em',
            textTransform: 'uppercase',
            fontWeight: 600,
            color: 'var(--prompt-white)',
            mixBlendMode: 'difference',
            pointerEvents: 'none',
            opacity: hovered ? 0 : 0.85,
            transition: 'opacity 200ms cubic-bezier(0.2,0.6,0.2,1)',
          }}
        >
          {caption}
        </div>
      )}

      {/* Divider line */}
      <div
        style={
          isHorizontal
            ? {
                position: 'absolute',
                left: 0,
                right: 0,
                top: `${pct}%`,
                height: 2,
                background: 'var(--prompt-yellow)',
                transform: 'translateY(-1px)',
                pointerEvents: 'none',
              }
            : {
                position: 'absolute',
                top: 0,
                bottom: 0,
                left: `${pct}%`,
                width: 2,
                background: 'var(--prompt-yellow)',
                transform: 'translateX(-1px)',
                pointerEvents: 'none',
              }
        }
      />

      {/* Handle — only in drag/horizontal modes */}
      {mode !== 'hover' && (
        <div
          style={
            isHorizontal
              ? {
                  position: 'absolute',
                  left: '50%',
                  top: `${pct}%`,
                  transform: 'translate(-50%, -50%)',
                  width: 56,
                  height: 28,
                  background: 'var(--prompt-yellow)',
                  border: '1.5px solid var(--prompt-black)',
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  pointerEvents: 'none',
                  gap: 4,
                }
              : {
                  position: 'absolute',
                  top: '50%',
                  left: `${pct}%`,
                  transform: 'translate(-50%, -50%)',
                  width: 28,
                  height: 56,
                  background: 'var(--prompt-yellow)',
                  border: '1.5px solid var(--prompt-black)',
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  flexDirection: 'column',
                  pointerEvents: 'none',
                  gap: 4,
                }
          }
        >
          <HandleArrows horizontal={isHorizontal} />
        </div>
      )}

      {/* Hover-mode crosshair indicator */}
      {mode === 'hover' && hovered && (
        <div
          style={{
            position: 'absolute',
            top: '50%',
            left: `${pct}%`,
            transform: 'translate(-50%, -50%)',
            width: 12,
            height: 12,
            background: 'var(--prompt-yellow)',
            border: '1.5px solid var(--prompt-black)',
            borderRadius: '50%',
            pointerEvents: 'none',
          }}
        />
      )}
    </div>
  );
}

function labelStyle(theme) {
  return {
    fontSize: 10,
    letterSpacing: '0.18em',
    textTransform: 'uppercase',
    fontWeight: 600,
    background: theme === 'dark' ? 'var(--prompt-black)' : 'var(--prompt-white)',
    color: theme === 'dark' ? 'var(--prompt-white)' : 'var(--prompt-black)',
    padding: '6px 10px',
    border: theme === 'dark' ? 'none' : '1px solid var(--prompt-black)',
  };
}

function HandleArrows({ horizontal }) {
  // Two small chevrons pointing outward
  const stroke = 'var(--prompt-black)';
  if (horizontal) {
    return (
      <svg width="22" height="14" viewBox="0 0 22 14" fill="none">
        <path d="M5 9 L2 7 L5 5" stroke={stroke} strokeWidth="1.5" strokeLinecap="square" />
        <path d="M17 5 L20 7 L17 9" stroke={stroke} strokeWidth="1.5" strokeLinecap="square" />
      </svg>
    );
  }
  return (
    <svg width="14" height="22" viewBox="0 0 14 22" fill="none">
      <path d="M5 5 L7 2 L9 5" stroke={stroke} strokeWidth="1.5" strokeLinecap="square" />
      <path d="M9 17 L7 20 L5 17" stroke={stroke} strokeWidth="1.5" strokeLinecap="square" />
    </svg>
  );
}

window.BeforeAfterSlider = BeforeAfterSlider;
