"use client";

import { ImgHTMLAttributes, useEffect, useState } from "react";
import { resolveImagePath } from "../../utils/helper";
import { FaSpinner } from "react-icons/fa6";

type UserImageProps = Omit<ImgHTMLAttributes<HTMLImageElement>, "src"> & {
  src?: string | null;
  fallbackSrc?: string;
};

export function UserImage({
  src,
  fallbackSrc = "/images/user-default.svg",
  alt = "User",
  onError,
  onLoad,
  ...props
}: UserImageProps) {
  const [imageSrc, setImageSrc] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    let isMounted = true;
    setIsLoading(true);

    const resolvedSrc = resolveImagePath(src) ?? fallbackSrc;
    const preload = new Image();
    preload.src = resolvedSrc;

    preload.onload = () => {
      if (!isMounted) return;
      setImageSrc(resolvedSrc);
      setIsLoading(false);
    };

    preload.onerror = () => {
      if (!isMounted) return;

      if (resolvedSrc === fallbackSrc) {
        // even the fallback failed, stop showing spinner
        setImageSrc(fallbackSrc);
        setIsLoading(false);
        return;
      }

      const fallbackPreload = new Image();
      fallbackPreload.src = fallbackSrc;
      fallbackPreload.onload = () => {
        if (!isMounted) return;
        setImageSrc(fallbackSrc);
        setIsLoading(false);
      };
      fallbackPreload.onerror = () => {
        if (!isMounted) return;
        setImageSrc(fallbackSrc);
        setIsLoading(false);
      };
    };

    return () => {
      isMounted = false;
    };
  }, [src, fallbackSrc]);

  return (
    <div className="relative inline-flex items-center justify-center w-full h-full">
      {isLoading && <FaSpinner className="size-5 animate-spin shrink-0" />}
      {!isLoading && imageSrc && (
        <img
          {...props}
          src={imageSrc}
          alt={alt}
          onLoad={onLoad}
          onError={onError}
        />
      )}
    </div>
  );
}
