/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment */
import {
  CheckCircleFill as CheckCircleIcon,
  ClockFill as PendingCircleIcon,
} from '@transferwise/icons';
import { clsx } from 'clsx';
import { ElementType, cloneElement, ReactNode } from 'react';
import { useIntl } from 'react-intl';

import Body from '../body';
import {
  Status,
  StatusDone,
  StatusNotDone,
  StatusPending,
  Size,
  Typography,
  Sentiment,
} from '../common';
import Info, { InfoProps } from '../info';
import StatusIcon from '../statusIcon';

import messages from './Summary.messages';
import { Action, ActionOptions } from '../common/action/Action';

const BadgeIcons = {
  [Status.DONE]: CheckCircleIcon,
  [Status.PENDING]: PendingCircleIcon,
};

const statusLabels = {
  [Status.NOT_DONE]: 'statusNotDone',
  [Status.DONE]: 'statusDone',
  [Status.PENDING]: 'statusPending',
};

const statusMapping = {
  [Status.DONE]: Sentiment.POSITIVE,
  [Status.PENDING]: Sentiment.PENDING,
};

export interface Props {
  /**
   * Action displayed at the bottom of the Summary
   */
  action?: ActionOptions;
  /**
   * Decides which html element should wrap the Summary
   */
  as?: ElementType;
  /**
   * Extra classes applied to Summary
   */
  className?: string;
  /**
   * @deprecated please use description instead
   */
  content?: ReactNode;
  /**
   * Summary description
   */
  description?: ReactNode;
  /**
   * @deprecated please use info instead
   */
  help?: {
    content: ReactNode;
    title?: ReactNode;
  };
  /**
   * Infos displayed on help Icon click inside Popover or Modal
   */
  info?: Pick<InfoProps, 'aria-label' | 'content' | 'onClick' | 'presentation' | 'title'>;
  /**
   * @deprecated please use icon instead
   */
  illustration?: ReactNode;
  /**
   * Main Summary Icon
   */
  icon?: ReactNode;
  /**
   * Decides the badge applied to Icon
   */
  status?: StatusNotDone | StatusDone | StatusPending;
  /**
   * Summary title
   */
  title: ReactNode;
}

const Summary = ({
  action,
  as: Element = 'div',
  className,
  content = null,
  description = content,
  help,
  icon,
  illustration = null,
  info = help,
  status,
  title,
}: Props) => {
  const intl = useIntl();

  let media = illustration;
  if (icon) {
    // @ts-expect-error if icon is present it has props and size prop
    const iconSize = icon?.props?.size as number;

    media =
      iconSize !== 24
        ? // @ts-expect-error we need icon to adjust it's size
          cloneElement(icon, { size: 24 })
        : icon;
  }
  // @ts-expect-error Badge can be null, this is handled in code
  const Badge = status && BadgeIcons[status];

  return (
    <Element
      className={clsx('np-summary d-flex align-items-start', className)}
      // @ts-expect-error we check whether `status` is not null before index `statusLabels` and `messages`
      aria-label={status && intl.formatMessage(messages[statusLabels[status]])}
    >
      <div className="np-summary__icon">
        {media}
        {Badge && (
          <div>
            {/* @ts-expect-error it's okey to pass `undefined` into `sentiment` prop */}
            <StatusIcon size={Size.SMALL} sentiment={statusMapping[status]} />
          </div>
        )}
      </div>
      <div className="np-summary__body m-l-2">
        <div className="np-summary__title d-flex">
          <Body
            as="span"
            role="heading"
            aria-level={6}
            type={Typography.BODY_LARGE_BOLD}
            className="text-primary m-b-1"
          >
            {title}
          </Body>
          {info && (
            <Info
              aria-label={info['aria-label']}
              className="m-l-1 hidden-xs"
              content={info.content}
              presentation={info.presentation}
              size={Size.LARGE}
              title={info.title}
              onClick={info.onClick}
            />
          )}
        </div>

        {description && (
          <Body
            as="span"
            type={Typography.BODY_DEFAULT}
            className="d-block np-summary__description"
          >
            {description}
          </Body>
        )}
        {action && <Action action={action} className="np-summary__action" />}
      </div>
      {info && (
        <Info
          aria-label={info['aria-label']}
          className="m-l-2 hidden-sm hidden-md hidden-lg hidden-xl"
          content={info.content}
          presentation={info.presentation}
          size={Size.LARGE}
          title={info.title}
          onClick={info.onClick}
        />
      )}
    </Element>
  );
};

export default Summary;
