/* 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 Link from '../link';
import type { AlertAction } from '../alert';

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?: AlertAction;
  /**
   * Decides which html element should wrap the Summary
   * @default 'div'
   */
  as?: ElementType;
  /**
   * Extra classes applied to Summary
   */
  className?: string;
  /**
   * @deprecated Use `description` instead.
   * @default null
   */
  content?: ReactNode;
  /**
   * Summary description
   */
  description?: ReactNode;
  /**
   * @deprecated 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 Use `icon` instead.
   * @default null
   */
  illustration?: ReactNode;
  /**
   * Main Summary Icon
   */
  icon?: ReactNode;
  /**
   * Decides the badge applied to Icon
   */
  status?: StatusNotDone | StatusDone | StatusPending;
  /**
   * Summary title
   */
  title: ReactNode;
}

/**
 * @deprecated Use `<ListItem />` instead (run codemod to migrate: **`npx @wise/wds-codemods@latest list-item`**).
 * @deprecatedSince 46.104.0
 * @see [Source](../listItem/ListItem.tsx)
 * @see [Storybook](https://storybook.wise.design/?path=/docs/content-listitem--docs)
 * @see [Design docs](https://wise.design/components/list-item)
 * @see [Release notes](https://transferwise.atlassian.net/wiki/spaces/DS/pages/3647251055/List+Item+release+notes)
 */
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]])}
    >
      {icon && (
        <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 ${icon ? '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 text-overflow-wrap 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 text-overflow-wrap ${icon ? 'np-summary__description' : 'np-summary__description-icon'}`}
          >
            {description}
          </Body>
        )}
        {action && (
          <Link
            href={action.href}
            target={action.target}
            className="np-summary__action"
            aria-label={action['aria-label']}
            onClick={action.onClick}
          >
            {action.text}
          </Link>
        )}
      </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;
