import { useEffect, useRef } from 'preact/hooks';
import { COPY } from './copy.js';
import { prefersReducedMotion } from './motion.js';

/**
 * El antes y después: el `diff` de daisyUI con la foto original DETRÁS
 * (`diff-item-2`) y el diseño generado DELANTE (`diff-item-1`).
 *
 * Las dos imágenes van con la misma proporción fija (la de `photo_size`) y
 * `object-cover` (lo pone el CSS del diff): el proveedor conserva la proporción
 * de la foto pero no su tamaño en píxeles, así que mostrarlas a su tamaño natural
 * las desalinearía.
 *
 * La revelación (`sweep`): el divisor lo mueve el ANCHO de `.diff-resizer`
 * (daisyUI 5) y `diff-item-1` ocupa esa columna. Arranca angosto (se ve la
 * original) y, 400 ms después de `ready` (el loader ya se fue), barre de
 * izquierda a derecha y descubre el diseño. Sin `sweep`, el divisor arranca en el
 * medio.
 * Al terminar, el ancho queda fijado en línea (`commitStyles`) para que el
 * visitante lo siga arrastrando. Con `prefers-reduced-motion`, sin barrido: queda
 * quieto en el medio.
 *
 * Sin la foto original (un diseño guardado que no entró con su vista previa), se
 * muestra solo el diseño.
 *
 * @param {{ original: string | null, result: string, ratio: number, sweep: boolean, ready: boolean }} props
 */
export default function Diff({ original, result, ratio, sweep, ready }) {
  const resizerRef = useRef(/** @type {HTMLDivElement | null} */ (null));
  const animated = sweep && !prefersReducedMotion();

  useEffect(() => {
    const resizer = resizerRef.current;
    if (!resizer || !animated || !ready) return undefined;
    let animation = null;
    const timer = setTimeout(() => {
      animation = resizer.animate([{ width: '1rem' }, { width: 'calc(100cqi - 1rem)' }], {
        duration: 1800,
        easing: 'cubic-bezier(0.65, 0, 0.35, 1)',
        fill: 'forwards',
      });
      animation.finished.then(
        () => {
          animation.commitStyles();
          animation.cancel();
        },
        () => undefined,
      );
    }, REVEAL_DELAY_MS);
    return () => {
      clearTimeout(timer);
      animation?.cancel();
    };
  }, [animated, ready]);

  if (!original) {
    return (
      <img
        src={result}
        alt={COPY.result.designAlt}
        class="h-full w-full rounded-2xl object-cover"
        style={{ aspectRatio: ratio }}
      />
    );
  }

  return (
    <figure
      class="ai-diff diff h-full w-full rounded-2xl"
      style={{ aspectRatio: ratio }}
      tabIndex={0}
    >
      <div class="diff-item-1" role="img" aria-label={COPY.result.designAlt} tabIndex={0}>
        <img src={result} alt="" />
      </div>
      <div class="diff-item-2" role="img" aria-label={COPY.result.originalAlt}>
        <img src={original} alt="" />
      </div>
      {/* Antes del barrido, angosto: se ve la original. */}
      <div ref={resizerRef} class="diff-resizer" style={animated ? { width: '1rem' } : undefined} />
    </figure>
  );
}

/**
 * Cuánto espera el barrido después de que el loader se fue. Con 1 s el diff
 * parecía quieto (feedback de la owner); con 0, el barrido arranca mientras el
 * ojo todavía sigue el fundido del loader y la «antes» no se registra. 400 ms
 * alcanzan para ver la foto original y que el barrido se lea como revelación.
 */
const REVEAL_DELAY_MS = 400;
