import React, { useCallback } from 'react';
import * as BaseAvatar from '@radix-ui/react-avatar';
import { clsx } from 'clsx';

import { Box } from '../box';
import { forwardRef } from '../utils/react';
import { AvatarDefaultFallback } from './avatar-default-fallback';
import * as css from './avatar.css';

export interface AvatarProps
  extends BaseAvatar.AvatarProps,
    Pick<BaseAvatar.AvatarImageProps, 'src' | 'srcSet' | 'sizes' | 'alt'> {
  fallback?: React.ReactNode;
}

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

type OnLoadingStatusChange = NonNullable<
  BaseAvatar.AvatarImageProps['onLoadingStatusChange']
>;

export const Avatar = forwardRef<'span', AvatarProps>(function Avatar(
  {
    as = 'span',
    children,
    className,
    src,
    srcSet,
    sizes,
    alt = 'Avatar',
    fallback,
    ...rest
  },
  ref,
) {
  const [status, setStatus] = React.useState<ImageLoadingStatus>('idle');

  const onLoadingStatusChange: OnLoadingStatusChange = useCallback(status => {
    setStatus(status);
  }, []);

  const cn = clsx(className, css.avatar);

  return (
    <BaseAvatar.Root asChild>
      <Box ref={ref} as={as} className={cn} {...rest}>
        <BaseAvatar.Image
          className={css.image}
          src={src}
          srcSet={srcSet}
          sizes={sizes}
          alt={alt}
          onLoadingStatusChange={onLoadingStatusChange}
        />

        {status === 'error' && (
          <BaseAvatar.Fallback className={css.fallback} delayMs={0}>
            {fallback || <AvatarDefaultFallback />}
          </BaseAvatar.Fallback>
        )}
      </Box>
    </BaseAvatar.Root>
  );
});
