import React, { ReactElement, ReactNode } from 'react';
import css from '../../utils/css';

import { CommonProps } from '../common';
import {
  ModalContainer,
  ModalOverlay,
  ModalContentWrapper,
  ModalContent,
  HeaderFooterWrapper,
} from './StyledModal';
import { useScrollLock } from './hooks';
import Divider from '../Divider';
import ModalBody from './ModalBody';
import ModalCloseButton from './ModalCloseButton';
import ModalContext from './ModalContext';
import ModalFooter from './ModalFooter';
import ModalHeader from './ModalHeader';

export interface ModalProps extends CommonProps {
  /**
   * Modal body.
   */
  body?: string | ReactElement;
  /**
   * Whether clicking outside the modal overlap to invoke onClose
   */
  canOutsideClickClose?: boolean;
  /**
   * Modal content. This will be placed after title, body & footer.
   */
  children?: ReactNode;
  /**
   * Modal footer.
   */
  footer?: string | ReactElement;
  /**
   * Closing callback. When onClose is available, an `x` button will be rendered on the right side of modal title. The callback will be called when user clicks on `x` button or outside of the modal (if canOutsideClickClose is set to true).
   */
  onClose?: () => void;
  /**
   * Open state of modal.
   */
  open?: boolean;
  /**
   * Modal size.
   * For xxlarge size: Before selecting this size, please consult with the design team.
   */
  size?: 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge';
  /**
   * Modal title.
   */
  title?: string | ReactElement;
  /**
   * Modal type.
   */
  variant?: 'basic' | 'primary';
}

const Modal = ({
  title,
  open = false,
  variant = 'primary',
  size = 'medium',
  onClose,
  canOutsideClickClose = true,
  body,
  footer,
  children,
  id,
  className,
  style,
  sx = {},
  'data-test-id': dataTestId,
}: ModalProps): ReactElement => {
  useScrollLock(open);

  return (
    <ModalContainer
      // eslint-disable-next-line no-unneeded-ternary
      themeOpen={open ? true : false}
      id={id}
      className={className}
      style={{ ...style, ...css(sx) }}
      data-test-id={dataTestId}
    >
      <ModalContext.Provider value={{ variant, isPopupModal: false }}>
        <ModalOverlay
          onClick={canOutsideClickClose === true ? onClose : undefined}
        />
        <ModalContentWrapper
          style={children === undefined ? { height: '100vh' } : undefined}
        >
          <ModalContent themeSize={size} data-test-id="modal-content">
            {title !== undefined && (
              <HeaderFooterWrapper>
                <ModalHeader>
                  {title}
                  {onClose !== undefined && (
                    <ModalCloseButton
                      data-test-id="modal-close-button"
                      onClick={(e): void => {
                        e.preventDefault();
                        onClose();
                      }}
                    />
                  )}
                </ModalHeader>
                {variant === 'basic' && <Divider marginX="medium" />}
              </HeaderFooterWrapper>
            )}
            {body !== undefined && <ModalBody>{body}</ModalBody>}
            {footer !== undefined && (
              <HeaderFooterWrapper>
                <Divider marginX="medium" />
                <ModalFooter>{footer}</ModalFooter>
              </HeaderFooterWrapper>
            )}
            {children}
          </ModalContent>
        </ModalContentWrapper>
      </ModalContext.Provider>
    </ModalContainer>
  );
};

export default Modal;
