import clsx from 'clsx';
import React from 'react';
import { IconName, Icons } from '../Icons';
import classes from './Message.scss';

export type MessageType = 'error' | 'info' | 'success' | 'warning';
type MessageClass = 'hasError' | 'hasInfo' | 'hasSuccess' | 'hasWarning';

export interface MessageProps {
  /** Title of the Message */
  title: string | React.ReactNode;
  /** Message type. default: ('error') */
  type?: MessageType;
  /** React element which will be rendered after the title */
  header?: JSX.Element;
  /** Determines if the body is rendered  (default: 'false')*/
  isBodyOpen?: boolean;
  /** Disables 'position: absolute' styling if set to false (default: true)*/
  isBodyPositionAbsolute?: boolean;
  /** Optional class */
  className?: string;
  /** Optional data-test-id. Defaults to 'message' */
  dataTestId?: string;
}

/**
 * Renders a contextual feedback message
 * Takes optional children which will be hidden by default. If the child is only a string, it will be wrapped in a '<p>' element.
 * @example
 * <Message type="error" title="An error has occurred" />
 */
export const Message: React.FC<MessageProps> = ({
  children,
  type = 'error',
  title,
  header,
  isBodyOpen = false,
  isBodyPositionAbsolute = true,
  className,
  dataTestId = 'message',
}) => {
  const state: {
    [Key in MessageType]: MessageClass;
  } = {
    error: 'hasError',
    info: 'hasInfo',
    success: 'hasSuccess',
    warning: 'hasWarning',
  };

  const icon: {
    [Key in MessageType]: IconName;
  } = {
    error: IconName.Error,
    info: IconName.Info,
    success: IconName.Success,
    warning: IconName.Warning,
  };

  return (
    <div
      className={clsx(
        classes.container,
        classes[state[type]],
        'message-container',
        className,
      )}
      data-test-id={dataTestId}
      data-test-type={type}
    >
      <div className={classes.titleWrapper}>
        <div className={clsx(classes.typeIcon)}>
          <Icons icon={icon[type]} className={classes.icon} />
        </div>

        <div className={classes.title}>
          <p data-test-id="message-title">{title}</p>
        </div>

        {header && <div className={classes.header}>{header}</div>}
      </div>
      {children && isBodyOpen && (
        <div
          className={clsx(classes.body, {
            [classes.absolute]: isBodyPositionAbsolute,
          })}
        >
          {children}
        </div>
      )}
    </div>
  );
};
