import React, {FC, useState} from 'react';
import {ImageStyle, StyleProp, View, ViewStyle} from 'react-native';
import {ImageLoadEventData} from 'expo-image';
import {IconProps, IconUser} from '@tabler/icons-react-native';
import {Typography, TypographyVariant} from '@components/_core/Typography';
import {Image, ImageProps} from '@components/_core/Image';
import {TUserName, getInitialLetters} from '@shared/utils';
import {ThemeAppearance, useTheme} from '@shared/theme';

import {getColorsVariant, getImageSizes, styles} from './styles';
import {AvatarBorderVariant, AvatarSize, AvatarVariant} from './interfaces';

export interface AvatarProps
  extends Omit<ImageProps, 'source' | 'resizeMode' | 'id'> {
  url?: Nullable<string>;
  name?: TUserName;
  emoji?: Nullable<string>;
  size?: AvatarSize;
  variant?: AvatarVariant;
  rounded?: boolean;
  Icon?: FC<IconProps>;
  iconColor?: string;
  iconFill?: string;
  appearance?: ThemeAppearance;
  customLabel?: string;
  borderVariant?: AvatarBorderVariant;
  onImageError?: () => void;
}

export function Avatar({
  url,
  name,
  emoji,
  style,
  Icon = IconUser,
  iconColor,
  rounded = true,
  size = 'md',
  variant = 'default',
  appearance = 'auto',
  iconFill = 'transparent',
  customLabel,
  borderVariant = 'none',
  enableCache = true,
  onImageError: onImageErrorProp,
  timeout = 15000,
  ...props
}: AvatarProps) {
  const {borderRadius, theme, colors} = useTheme();
  const [showLetters, setShowLetters] = useState(false);
  const {backgroundColor, color} = getColorsVariant({
    variant,
    appearance,
    theme,
  });
  const {containerSize, contentSize} = getImageSizes(size);
  const letters = getInitialLetters(name);
  const showImage = url && !showLetters;
  const textVariant: TypographyVariant =
    size === 'xxl' ? 'xxl' : size === 'xl' ? 'l' : 'xs';

  const onImageLoad = (evt: ImageLoadEventData) => {
    setShowLetters(false);

    props.onLoad?.(evt);
  };

  const onImageError = () => {
    onImageErrorProp?.();
    setShowLetters(true);
  };

  const propStyles: ImageStyle = {
    width: containerSize,
    height: containerSize,
    borderRadius: rounded ? containerSize : borderRadius.m,
    backgroundColor: showImage ? colors.transparent : backgroundColor,
    ...(borderVariant === 'live'
      ? {borderColor: theme.graphics.error[500], ...styles.live}
      : {}),
  };

  return showImage ? (
    <Image
      source={{uri: url}}
      contentFit="cover"
      // Disable the default cross-fade — placeholder → main should be a
      // straight cut so it doesn't look like an opacity animation.
      transition={0}
      onLoad={onImageLoad}
      onError={onImageError}
      style={[propStyles, style]}
      enableCache={enableCache}
      // Avatars: memory + disk so re-renders within a session paint
      // instantly from memory and cold launches still skip the network.
      cachePolicy="memory-disk"
      // Avatars are tiny — 3 s is more than enough to load one. If it
      // takes longer something's wrong, kick the auto-retry funnel.
      timeout={timeout}
      recyclingKey={url}
      {...props}
    />
  ) : emoji ? (
    <Typography
      style={styles.emoji}
      weight="semiBold"
      color={color}
      adjustsFontSizeToFit>
      {emoji}
    </Typography>
  ) : (
    <View style={[propStyles, styles.container, style] as StyleProp<ViewStyle>}>
      {customLabel || letters.length ? (
        <Typography
          variant={textVariant}
          weight="semiBold"
          color={color}
          numberOfLines={1}
          adjustsFontSizeToFit>
          {customLabel ?? letters}
        </Typography>
      ) : (
        <Icon size={contentSize} color={iconColor || color} fill={iconFill} />
      )}
    </View>
  );
}

export * from './interfaces';
