import { Info, Alert, Cross, Check, ClockBorderless } from '@transferwise/icons';
import { clsx } from 'clsx';
import { useIntl } from 'react-intl';

import { SizeSmall, SizeMedium, SizeLarge, Sentiment, Size, Breakpoint } from '../common';
import Circle, { CircleProps } from '../common/circle';
import { useMedia } from '../common/hooks/useMedia';

import messages from './StatusIcon.messages';

export type StatusIconProps = {
  sentiment: `${Sentiment}`;
  size: SizeSmall | SizeMedium | SizeLarge;
  /**
   * Override for the sentiment's-derived, default, accessible
   * name announced by the screen readers. <br />
   * Using `null` will render the icon purely presentational.
   * */
  iconLabel?: string | null;
};

const mapLegacySize = {
  [String(Size.SMALL)]: 16,
  [String(Size.MEDIUM)]: 40,
  [String(Size.LARGE)]: 48,
} satisfies Record<string, CircleProps['size']>;

const StatusIcon = ({
  sentiment = 'neutral',
  size: sizeProp = 'md',
  iconLabel,
}: StatusIconProps) => {
  const intl = useIntl();

  const iconMetaBySentiment: Record<
    `${Sentiment}`,
    {
      Icon: React.ElementType;
      defaultIconLabel: string;
    }
  > = {
    [Sentiment.NEGATIVE]: {
      Icon: Cross,
      defaultIconLabel: intl.formatMessage(messages.errorLabel),
    },
    [Sentiment.POSITIVE]: {
      Icon: Check,
      defaultIconLabel: intl.formatMessage(messages.successLabel),
    },
    [Sentiment.WARNING]: {
      Icon: Alert,
      defaultIconLabel: intl.formatMessage(messages.warningLabel),
    },
    [Sentiment.PENDING]: {
      Icon: ClockBorderless,
      defaultIconLabel: intl.formatMessage(messages.pendingLabel),
    },
    [Sentiment.NEUTRAL]: {
      Icon: Info,
      defaultIconLabel: intl.formatMessage(messages.informationLabel),
    },
    // deprecated
    [Sentiment.ERROR]: {
      Icon: Cross,
      defaultIconLabel: intl.formatMessage(messages.errorLabel),
    },
    [Sentiment.INFO]: {
      Icon: Info,
      defaultIconLabel: intl.formatMessage(messages.informationLabel),
    },
    [Sentiment.SUCCESS]: {
      Icon: Check,
      defaultIconLabel: intl.formatMessage(messages.successLabel),
    },
  };
  const { Icon, defaultIconLabel } = iconMetaBySentiment[sentiment];

  const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
  const isTinyViewport = useMedia(`(max-width: ${Breakpoint.ZOOM_400}px)`);
  const size = sizeProp === Size.SMALL && isTinyViewport ? 32 : mapLegacySize[sizeProp];
  return (
    <Circle
      as="span"
      size={size}
      data-testid="status-icon"
      className={clsx('status-circle', `status-circle-${sizeProp}`, sentiment)}
    >
      <Icon
        className={clsx('status-icon', iconColor)}
        title={iconLabel === null ? undefined : iconLabel || defaultIconLabel}
      />
    </Circle>
  );
};

export default StatusIcon;
