import Badge, { BadgeAssets, BadgeProps, BadgeAssetsProps } from '../badge';
import NotificationDot from './NotificationDot';
import Circle from '../common/circle';
import Image from '../image';
import { HTMLAttributes, PropsWithChildren, useState } from 'react';
import { clsx } from 'clsx';
import { getInitials, Size } from '../common';
import {
  Briefcase as BusinessProfileIcon,
  Profile as PersonalProfileIcon,
} from '@transferwise/icons';

export type Props = {
  imgSrc?: string | null;
  /**
   * Entity name (person (profile or recipient) or business name), it will be boilded down to 1 or 2 chars (initials)
   */
  name?: string | null;
  type?: 'personal' | 'business';
  size?: 16 | 24 | 32 | 40 | 48 | 56 | 72;
  notification?: boolean;
  badge?: BadgeAssetsProps;
  interactive?: boolean;
  selected?: boolean;
  style?: Pick<React.CSSProperties, 'border' | 'backgroundColor' | 'color'>;
} & Pick<
  HTMLAttributes<HTMLDivElement>,
  'className' | 'children' | 'role' | 'aria-label' | 'aria-labelledby' | 'aria-describedby'
>;

function AvatarView({
  children = undefined,
  size = 48,
  selected,
  notification,
  badge,
  interactive = false,
  className,
  style,
  imgSrc,
  type,
  name,
  ...restProps
}: Props) {
  return (
    <Circle
      size={size}
      fixedSize
      className={clsx(
        'np-avatar-view',
        interactive ? 'np-avatar-view-interactive' : 'np-avatar-view-non-interactive',
        { 'np-avatar-view-selected': selected },
        className,
      )}
      {...restProps}
    >
      <Badges avatar={{ size, notification, selected }} {...badge}>
        <Circle
          size={size}
          fixedSize
          className={clsx('np-avatar-view-content')}
          enableBorder={!interactive || selected}
          style={{
            ...(selected && { '--circle-border-color': 'var(--color-interactive-primary)' }),
            ...style,
          }}
        >
          {children === undefined ? <Profile {...{ imgSrc, type, name }} /> : children}
        </Circle>
      </Badges>
    </Circle>
  );
}

/** Size of badge depends on size of avatar */
const MAP_BADGE_ASSET_SIZE = {
  16: 'sm',
  24: 'sm',
  32: 'sm',
  40: 'sm',
  48: 'sm',
  56: 'lg',
  72: 'lg',
};

/** Certain sizes of AvatarView has a custom offset of Badge */
const MAP_BADGE_POSITION = {
  24: -6,
  32: -4,
};

type BadgesProps = BadgeAssetsProps &
  PropsWithChildren<{
    avatar: Pick<Props, 'selected' | 'size' | 'notification'>;
  }>;

/**
 * Adds build-in badges to AvatarView
 */
function Badges({ children, avatar, ...badge }: BadgesProps) {
  const { size = 48, selected, notification } = avatar;
  const anyCustomBadge = Object.keys(badge).length > 0;
  if ((anyCustomBadge || selected) && size > 16) {
    const badgeSize: BadgeProps['size'] = MAP_BADGE_ASSET_SIZE[size] ?? Size.SMALL;
    return (
      <Badge
        size={badgeSize}
        badge={<BadgeAssets {...(selected ? { status: 'positive' } : badge)} size={badgeSize} />}
        style={{
          // @ts-expect-error CSS custom props allowed
          '--badge-content-position': `${MAP_BADGE_POSITION[size] ?? 0}px`,
        }}
      >
        {children}
      </Badge>
    );
  }
  if (notification) {
    return <NotificationDot avatarSize={size}>{children}</NotificationDot>;
  }
  return children;
}

/**
 * Common logic for entities (personal & business profiles or recipients)
 */
function Profile({ imgSrc, name, type }: Pick<Props, 'imgSrc' | 'name' | 'type'>) {
  const [tryLoadImage, setTryLoadImage] = useState(true);
  if (imgSrc && tryLoadImage) {
    return <Image src={imgSrc} alt="" onError={() => setTryLoadImage(false)} />;
  }
  if (type) {
    return type.toLowerCase() === 'business' ? <BusinessProfileIcon /> : <PersonalProfileIcon />;
  }
  if (name) {
    return getInitials(name);
  }
  return <PersonalProfileIcon />;
}

export default AvatarView;
