import { useRef, useState, type CSSProperties } from "react";

interface BeforeAfterCompareProps {
  sourceSrc: string;
  resultSrc: string;
  sourceLabel?: string;
  resultLabel?: string;
  sourceAlt?: string;
  resultAlt?: string;
  className?: string;
  onSourceLoad?: (width: number, height: number) => void;
}

const MIN_POSITION = 5;
const MAX_POSITION = 95;

function clamp(value: number) {
  return Math.min(MAX_POSITION, Math.max(MIN_POSITION, value));
}

export default function BeforeAfterCompare({
  sourceSrc,
  resultSrc,
  sourceLabel,
  resultLabel,
  sourceAlt = "原图",
  resultAlt = "结果",
  className = "",
  onSourceLoad,
}: BeforeAfterCompareProps) {
  const stageRef = useRef<HTMLDivElement>(null);
  const [position, setPosition] = useState(50);

  const updatePosition = (clientX: number) => {
    const stage = stageRef.current;
    if (!stage) return;
    const rect = stage.getBoundingClientRect();
    if (!rect.width) return;
    setPosition(clamp(((clientX - rect.left) / rect.width) * 100));
  };

  return (
    <div
      ref={stageRef}
      className={`before-after-compare ${className}`}
      style={{ "--compare-position": `${position}%` } as CSSProperties}
      aria-label="前后对比"
    >
      <div className="before-after-compare__layer before-after-compare__layer--source">
        <img
          src={sourceSrc}
          alt={sourceAlt}
          onLoad={(event) => {
            onSourceLoad?.(event.currentTarget.naturalWidth, event.currentTarget.naturalHeight);
          }}
        />
      </div>
      <div className="before-after-compare__layer before-after-compare__layer--result">
        <img src={resultSrc} alt={resultAlt} />
      </div>
      {sourceLabel && (
        <div className="before-after-compare__label before-after-compare__label--source">{sourceLabel}</div>
      )}
      {resultLabel && (
        <div className="before-after-compare__label before-after-compare__label--result">{resultLabel}</div>
      )}
      <div
        className="before-after-compare__divider"
        role="slider"
        tabIndex={0}
        aria-label="拖动对比"
        aria-valuemin={MIN_POSITION}
        aria-valuemax={MAX_POSITION}
        aria-valuenow={Math.round(position)}
        onKeyDown={(event) => {
          if (event.key === "ArrowLeft") {
            event.preventDefault();
            setPosition((current) => clamp(current - 2));
          }
          if (event.key === "ArrowRight") {
            event.preventDefault();
            setPosition((current) => clamp(current + 2));
          }
        }}
        onPointerDown={(event) => {
          event.currentTarget.setPointerCapture(event.pointerId);
          updatePosition(event.clientX);
        }}
        onPointerMove={(event) => {
          if (!event.currentTarget.hasPointerCapture(event.pointerId)) return;
          updatePosition(event.clientX);
        }}
        onPointerUp={(event) => {
          if (event.currentTarget.hasPointerCapture(event.pointerId)) {
            event.currentTarget.releasePointerCapture(event.pointerId);
          }
        }}
        onPointerCancel={(event) => {
          if (event.currentTarget.hasPointerCapture(event.pointerId)) {
            event.currentTarget.releasePointerCapture(event.pointerId);
          }
        }}
      >
        <span />
      </div>
    </div>
  );
}
