import { Image } from 'expo-image'
import type { ReactNode } from 'react'
import { Text, useTheme, View } from 'tamagui'

export type SiteAvatarSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg'

type SizeSpec = { px: number; font: number }

export const SITE_AVATAR_SIZES: Record<SiteAvatarSize, SizeSpec> = {
  xxs: { px: 16, font: 9 },
  xs: { px: 24, font: 12 },
  sm: { px: 32, font: 14 },
  md: { px: 40, font: 16 },
  lg: { px: 96, font: 32 },
}

export type SiteAvatarShape = 'circle' | 'rounded'

export type SiteAvatarBorder = 'default' | 'none' | 'contrast'

type Props = {
  url?: string | null
  size?: SiteAvatarSize
  initial?: string
  shape?: SiteAvatarShape
  borderStyle?: SiteAvatarBorder
  priority?: 'high' | 'low'
  // Per expo-image's FlashList guidance: when a recycled cell is repointed to
  // a different account, changing `recyclingKey` resets the image view to
  // blank/placeholder before the new avatar loads, killing the cross-row
  // flicker where the previous account's avatar lingers. Pass the account id
  // from inside a recycled list row; leave undefined elsewhere.
  recyclingKey?: string
  onLoad?: () => void
  onError?: () => void
  accessibilityLabel?: string
}

export default function SiteAvatar({
  url,
  size = 'md',
  initial,
  shape = 'circle',
  borderStyle = 'default',
  priority = 'high',
  recyclingKey,
  onLoad,
  onError,
  accessibilityLabel,
}: Props): ReactNode {
  const theme = useTheme()
  const { px, font } = SITE_AVATAR_SIZES[size]

  const borderWidth = borderStyle === 'contrast' ? 2 : borderStyle === 'none' ? 0 : 1
  const borderColor =
    borderStyle === 'contrast'
      ? theme.background.val
      : borderStyle === 'none'
        ? 'transparent'
        : theme.borderColor.val
  const radius = shape === 'circle' ? px / 2 : Math.max(3, Math.round(px * 0.22))

  const initialChar = initial?.trim().charAt(0).toUpperCase() || ''

  return (
    <View
      collapsable={false}
      width={px}
      height={px}
      borderRadius={radius}
      borderWidth={borderWidth}
      borderColor={borderColor}
      backgroundColor={theme.backgroundTertiary.val}
      overflow="hidden"
      alignItems="center"
      justifyContent="center"
    >
      {url ? (
        <Image
          source={{ uri: url }}
          style={{ width: px, height: px }}
          contentFit="cover"
          cachePolicy="memory-disk"
          priority={priority}
          transition={180}
          recyclingKey={recyclingKey}
          onLoad={onLoad}
          onError={onError}
          accessibilityLabel={accessibilityLabel}
        />
      ) : initialChar ? (
        <Text color={theme.color.val} fontSize={font} fontWeight="600">
          {initialChar}
        </Text>
      ) : null}
    </View>
  )
}
