import { clsx } from 'clsx';
import { MouseEvent, type ReactNode, forwardRef, useRef } from 'react';

import { CloseButton } from '../closeButton';
import { stopPropagation } from '../domHelpers';

export interface CardProps {
  /** Content to display inside Card. */
  children: ReactNode;

  /** Optional prop to specify classNames onto the Card */
  className?: string;

  /** Optional prop to specify the ID on to Card  */
  id?: string;

  /** Specify whether the Card is disabled, or not */
  isDisabled?: boolean;

  /** Specify whether the Card is sized small or not */
  isSmall?: boolean;

  /** Optionally specify Card onDismiss function */
  onDismiss?: () => void;

  /** Optional prop to specify the ID used for testing */
  testId?: string;
}

/**
 * Card component.
 *
 * A card is a container for content that is used to group related information.
 * It can be used to display information in a structured way, and can be
 * customized with various props to suit different use cases.
 *
 * @param {Object} props - The component props.
 * @param {ReactNode} children - The content to display inside the card.
 * @param {string} className - Optional class name(s) to add to the card container.
 * @param {string} id - Optional ID to add to the card container.
 * @param {boolean} isDisabled - Whether the card is disabled or not.
 * @param {boolean} isSmall - Whether the card is small or not.
 * @param {(event_: MouseEvent<HTMLButtonElement>) => void} onDismiss - Optional function to call when the card is dismissed.
 * @param {string} testId - Optional ID to add to the card container for testing purposes.
 * @returns {React.JSX.Element} - The card component.
 * @example
 * <Card>
 *   <p>Hello World!</p>
 * </Card>
 */
const Card = forwardRef<HTMLDivElement, CardProps>(
  (
    {
      className,
      children = null,
      id,
      isDisabled = false,
      isSmall = false,
      onDismiss,
      testId,
      ...props
    },
    ref,
  ) => {
    const closeButtonReference = useRef(null);

    return (
      <div
        ref={ref}
        className={clsx(
          'np-Card',
          {
            'np-Card--small': !!isSmall,
            'is-disabled': !!isDisabled,
          },
          className,
        )}
        id={id}
        data-testid={testId}
        {...props}
      >
        {onDismiss && (
          <CloseButton
            ref={closeButtonReference}
            className="np-Card-closeButton"
            size={isSmall ? 'sm' : 'md'}
            isDisabled={isDisabled}
            testId="close-button"
            onClick={(e) => {
              stopPropagation(e);
              onDismiss();
            }}
          />
        )}
        {children}
      </div>
    );
  },
);

Card.displayName = 'Card';

export default Card;
