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, Status } from '../common';
import Circle, { CircleProps } from '../common/circle';
import { useMedia } from '../common/hooks/useMedia';

import messages from './StatusIcon.messages';

/**
 * @deprecated Use `16 | 24 | 32 | 40 | 48 | 56 | 72` instead.
 */
type LegacySizes = SizeSmall | SizeMedium | SizeLarge;

export type StatusIconSentiment = Sentiment | Status.PENDING;

export type StatusIconProps = {
  id?: string;
  /** @default 'neutral' */
  sentiment?: `${StatusIconSentiment}`;
  /** @default 40 */
  size?: LegacySizes | 16 | 24 | 32 | 40 | 48 | 56 | 72;
  /**
   * 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 = ({
  id,
  sentiment = 'neutral',
  size: sizeProp = 40,
  iconLabel,
}: StatusIconProps) => {
  const intl = useIntl();

  const iconMetaBySentiment: Record<
    `${Sentiment}` | Status.PENDING,
    {
      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),
    },
    [Status.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 isTinyViewport = useMedia(`(max-width: ${Breakpoint.ZOOM_400}px)`);
  const size = mapLegacySize[sizeProp] ?? sizeProp;

  return (
    <Circle
      size={isTinyViewport && size < 40 ? 32 : size}
      data-testid="status-icon"
      className={clsx('status-circle', sentiment)}
      id={id}
    >
      <Icon
        className="status-icon"
        title={iconLabel === null ? undefined : iconLabel || defaultIconLabel}
      />
    </Circle>
  );
};

export default StatusIcon;
