import { ImageOff } from "lucide-react";
import { useEffect, useMemo, useState } from "react";

type BubbleImageProps = {
  src: string | undefined;
  /**
   * Optional absolute URL(s) to try if `src` fails to load. Useful when `src`
   * is an optimized-but-fragile thumbnail (e.g. a root-relative thumbnailUrl)
   * and we want to fall back to the reliable full-size asset before giving up.
   */
  fallbackSrc?: string | (string | undefined)[];
  className?: string;
  loading?: "lazy" | "eager";
  /**
   * Called once the active source loads, with the image's intrinsic pixel
   * size. Lets callers (e.g. single-image bubbles) adopt the real aspect
   * ratio without depending on backend-provided width/height.
   */
  onNaturalSize?: (width: number, height: number) => void;
};

/**
 * Thumbnail <img> for message bubbles. Renders with an empty alt (decorative)
 * and, if every candidate source fails to load, falls back to a neutral
 * placeholder instead of the browser's broken-image box — which would otherwise
 * expose the raw file name via alt text.
 */
export function BubbleImage({
  src,
  fallbackSrc,
  className,
  loading,
  onNaturalSize,
}: BubbleImageProps) {
  // Ordered, de-duplicated list of sources to attempt in turn.
  const candidates = useMemo(() => {
    const extra = Array.isArray(fallbackSrc) ? fallbackSrc : [fallbackSrc];
    return [src, ...extra].filter(
      (value, index, all): value is string =>
        !!value && all.indexOf(value) === index,
    );
  }, [src, fallbackSrc]);

  const [attempt, setAttempt] = useState(0);

  // Reset when the candidate set changes so a reused element re-attempts.
  useEffect(() => {
    setAttempt(0);
  }, [candidates]);

  const current = candidates[attempt];

  if (!current) {
    return (
      <div
        className={`flex items-center justify-center bg-gradient-to-br from-neutral-800 to-neutral-900 ${
          className ?? ""
        }`}
        aria-hidden
      >
        <ImageOff className="h-8 w-8 text-neutral-600" />
      </div>
    );
  }

  return (
    <img
      src={current}
      alt=""
      loading={loading}
      decoding="async"
      className={`ark-img-fade ${className ?? ""}`}
      onLoad={(e) => {
        const img = e.currentTarget;
        // Fade each image in as soon as it loads, so they appear progressively
        // instead of the page seeming to wait for everything.
        img.classList.add("is-loaded");
        if (img.naturalWidth && img.naturalHeight)
          onNaturalSize?.(img.naturalWidth, img.naturalHeight);
      }}
      onError={() => setAttempt((i) => i + 1)}
    />
  );
}
