import * as React from "react";
import { useAvatarContext } from "./avatar";

type ImageLoadingStatus = "idle" | "loading" | "loaded" | "error";

export type AvatarImageProps = Omit<
	React.ImgHTMLAttributes<HTMLImageElement>,
	"src"
> & {
	/**
	 * The image source URL. If empty or undefined, triggers error state.
	 */
	src?: string | null;

	/**
	 * Callback when the image loading status changes.
	 */
	onLoadingStatusChange?: (status: ImageLoadingStatus) => void;
};

/**
 * Image component that syncs its loading state with the Avatar context.
 * Automatically hides when loading fails, allowing fallback to show.
 *
 * @example
 * ```tsx
 * <Avatar>
 *   <AvatarImage src="/photo.jpg" alt="User" />
 *   <AvatarFallback name="John Doe" />
 * </Avatar>
 * ```
 */
export const AvatarImage = React.forwardRef<HTMLImageElement, AvatarImageProps>(
	(
		{ src, alt = "", className, style, onLoadingStatusChange, ...props },
		ref
	) => {
		const { imageLoadingStatus, onImageLoadingStatusChange } =
			useAvatarContext();

		const imageRef = React.useRef<HTMLImageElement>(null);
		// biome-ignore lint/style/noNonNullAssertion: ref is guaranteed to be set
		React.useImperativeHandle(ref, () => imageRef.current!);

		const updateStatus = React.useCallback(
			(status: ImageLoadingStatus) => {
				onImageLoadingStatusChange(status);
				onLoadingStatusChange?.(status);
			},
			[onImageLoadingStatusChange, onLoadingStatusChange]
		);

		React.useLayoutEffect(() => {
			if (!src) {
				updateStatus("error");
				return;
			}

			let isMounted = true;
			const image = new Image();

			const setStatus = (status: ImageLoadingStatus) => {
				if (!isMounted) {
					return;
				}
				updateStatus(status);
			};

			setStatus("loading");

			image.onload = () => setStatus("loaded");
			image.onerror = () => setStatus("error");
			image.src = src;

			return () => {
				isMounted = false;
			};
		}, [src, updateStatus]);

		if (imageLoadingStatus !== "loaded") {
			return null;
		}

		return (
			// biome-ignore lint/performance/noImgElement: This is a library component, not a Next.js app
			// biome-ignore lint/nursery/useImageSize: Size is controlled by parent container
			<img
				alt={alt}
				className={className}
				data-avatar-image=""
				ref={imageRef}
				src={src ?? undefined}
				style={{
					aspectRatio: "1 / 1",
					width: "100%",
					height: "100%",
					objectFit: "cover",
					...style,
				}}
				{...props}
			/>
		);
	}
);

AvatarImage.displayName = "AvatarImage";
