import { IdIconProps } from '@transferwise/icons';
import { clsx } from 'clsx';
import { FC, ReactNode, cloneElement, useId } from 'react';

import Body from '../../body';
import Chevron from '../../chevron';
import { Position, Size, Typography } from '../../common';
import Option from '../../common/Option';

export interface AccordionItemProps {
  /** A label for the accordion item, used for accessibility purposes. */
  'aria-label'?: string;
  /** An ID for the accordion item, used for accessibility purposes. */
  id?: string;
  /** The title of the accordion item. */
  title: ReactNode;
  /** The subtitle of the accordion item. */
  subtitle?: ReactNode;
  /** The content of the accordion item. */
  content: ReactNode;
  /** A callback function that is called when the accordion item is clicked. */
  onClick: () => void;
  /** Whether the accordion item is currently open or closed. */
  open: boolean;
  /** An optional icon to display next to the accordion item title. */
  icon?: ReactNode;
  /** An optional media element to display next to the accordion item title. */
  media?: ReactNode;
  /** An optional showMediaAtAllSizes with media available at all sizes of the screen. */
  showMediaAtAllSizes?: boolean;
  /** An optional showMediaCircle to display media within the circle. */
  showMediaCircle?: boolean;
  /** An optional isContainerAligned to display media aligned with the container. */
  isContainerAligned?: boolean;
  /** @deprecated ... */
  theme?: 'light' | 'dark';
}

/**
 * AccordionItem
 *
 * A single item in an accordion component.
 *
 * @component
 * @param {string} [aria-label] - A label for the accordion item, used for accessibility purposes.
 * @param {string} [id] - An ID for the accordion item, used for accessibility purposes.
 * @param {ReactNode} title - The title of the accordion item.
 * @param {ReactNode} subtitle - The subtitle of the accordion item.
 * @param {ReactNode} content - The content of the accordion item.
 * @param {Function} onClick - A callback function that is called when the accordion item is clicked.
 * @param {boolean} open - Whether the accordion item is currently open or closed.
 * @param {ReactNode} [icon] - An optional icon to display next to the accordion item title.
 * @param {ReactNode} [media] - An optional media to display next to the accordion item.
 * @param {boolean} [showMediaAtAllSizes] - An optional showMediaAtAllSizes with media available at all sizes of the screen.
 * @param {boolean} [showMediaCircle] - An optional showMediaCircle to display media within the circle.
 * @param {boolean} [isContainerAligned] - An optional isContainerAligned to display media aligned with the container.
 * @example
 * // Example usage:
 *
 * import AccordionItem from './AccordionItem';
 *
 * function App() {
 *   const handleItemClick = () => {
 *     console.log('Accordion item was clicked.');
 *   };
 *
 *   return (
 *     <AccordionItem
 *       title={<h2>Item Title</h2>}
 *       content={<p>Item content goes here.</p>}
 *       onClick={handleItemClick}
 *       open={true}
 *       icon={<Chevron />}
 *     />
 *   );
 * }
 */
const AccordionItem: FC<AccordionItemProps> = ({
  'aria-label': ariaLabel,
  id,
  title,
  subtitle,
  content,
  onClick,
  open,
  icon,
  media,
  showMediaAtAllSizes,
  showMediaCircle,
  isContainerAligned,
  theme = 'light',
}) => {
  const mediaElement = icon
    ? cloneElement(icon as React.ReactElement<IdIconProps>, { size: 24 })
    : media;
  const fallbackId = useId();
  const accordionId = id ?? fallbackId;

  return (
    <div
      id={accordionId}
      className={clsx('np-accordion-item', {
        'np-accordion-item--open': open,
        'np-accordion-item--with-icon': Boolean(icon),
        'np-accordion-item--with-media': Boolean(media),
      })}
    >
      <Option
        aria-label={ariaLabel}
        as="button"
        media={mediaElement}
        title={title}
        content={subtitle}
        button={<Chevron orientation={open ? Position.TOP : Position.BOTTOM} size={Size.MEDIUM} />}
        inverseMediaCircle={false}
        aria-expanded={open}
        aria-controls={`${accordionId}-section`}
        id={`${accordionId}-control`}
        showMediaCircle={showMediaCircle}
        showMediaAtAllSizes={showMediaAtAllSizes}
        isContainerAligned={isContainerAligned}
        onClick={onClick}
      />
      {open && (
        <div id={`${accordionId}-section`} role="region" aria-labelledby={`${accordionId}-control`}>
          <Body
            as="span"
            type={Typography.BODY_LARGE}
            className={clsx('np-accordion-item__content', 'd-block', {
              'has-icon': icon,
            })}
          >
            {content}
          </Body>
        </div>
      )}
    </div>
  );
};

export default AccordionItem;
