import { useRef } from 'react'

import { styled, useStyleConfig, vui, VuiComponent } from '../core'
import { Modal } from '../modal'
import { cs, isJsx, isReactText, random, useIds } from '../utils'
import { modalAnimation, modalJustifyContent } from './consts'
import { DialogProvider } from './context'
import { DialogProps } from './dialog.types'
import DialogBody from './dialogBody'
import DialogCancelButton from './dialogCancelButton'
import DialogCloseButton from './dialogCloseButton'
import DialogFooter from './dialogFooter'
import DialogHeader from './dialogHeader'
import DialogIcon from './dialogIcon'
import DialogSubmitButton from './dialogSubmitButton'
import DialogTitle from './dialogTitle'

export const DialogBase = styled.divBox`
  background-color: white;
  border-radius: 1px;
  box-shadow: modal;
  display: flex;
  flex-direction: column;
  width: 100%;
`

/**
 * Displays content in a Modal window. Includes required accessibility configuration.
 *
 * Dialog is built upon `Modal`.
 *
 * The content can include important information, like warnings or errors, simple forms or prompts for user's decision. It blocks interaction with the rest of the page, but often can be disabled by pressing Escape, clicking on the backdrop or close button.
 */
export const Dialog = vui<'div', DialogProps>((props, ref) => {
  const {
    body: bodyProp,
    cancelButton,
    children,
    className,
    closeButton,
    disableBackdropClose,
    footer,
    header,
    icon,
    id,
    isOpen,
    modalProps: modalPropsProp,
    placement = 'center',
    onClose,
    size,
    status,
    submitButton,
    title,
    variant,
    ...rest
  } = props
  const styles = useStyleConfig('Dialog', props)

  const idRef = useRef(id ?? random().toString())
  const [dialogId, bodyId, titleId] = useIds(idRef.current, ['dialog', 'dialog-body', 'dialog-title'])

  const body = isReactText(bodyProp) ? { children: bodyProp } : bodyProp
  const showHeader = Boolean(header || closeButton || icon || title)
  const showFooter = Boolean(footer || cancelButton || submitButton)

  const ariaProps = {
    'aria-describedby': bodyId,
    'aria-labelledby': titleId,
  }

  const modalProps = {
    animation: modalAnimation[placement as keyof typeof modalAnimation],
    contentProps: {
      alignItems: placement === 'center' ? 'center' : 'auto',
      justifyContent: modalJustifyContent[placement as keyof typeof modalJustifyContent],
      ...modalPropsProp?.contentProps,
    },
    ...modalPropsProp,
  }

  const context = { bodyId, icon, isOpen, onClose, size, status, titleId, variant }

  return (
    <DialogProvider value={context}>
      <Modal {...{ isOpen, onClose }} {...{ ...modalProps, disableBackdropClose }}>
        <DialogBase
          className={cs('vui-dialog', className)}
          id={dialogId}
          maxH={placement === 'center' ? 'calc(100vh - 32px)' : '100%'}
          ref={ref}
          role="dialog"
          {...ariaProps}
          {...styles.container}
          {...rest}
        >
          {children ?? (
            <>
              {isJsx(header) ? header : showHeader && <DialogHeader {...{ closeButton, icon, title }} {...header} />}

              {isJsx(body) ? body : body && <DialogBody {...body} />}

              {isJsx(footer) ? footer : showFooter && <DialogFooter {...{ cancelButton, submitButton }} {...footer} />}
            </>
          )}
        </DialogBase>
      </Modal>
    </DialogProvider>
  )
}) as VuiComponent<'div', DialogProps> & {
  Body: typeof DialogBody
  CancelButton: typeof DialogCancelButton
  CloseButton: typeof DialogCloseButton
  Footer: typeof DialogFooter
  Header: typeof DialogHeader
  Icon: typeof DialogIcon
  SubmitButton: typeof DialogSubmitButton
  Title: typeof DialogTitle
}

Dialog.Body = DialogBody
Dialog.CancelButton = DialogCancelButton
Dialog.CloseButton = DialogCloseButton
Dialog.Footer = DialogFooter
Dialog.Header = DialogHeader
Dialog.Icon = DialogIcon
Dialog.SubmitButton = DialogSubmitButton
Dialog.Title = DialogTitle
Dialog.displayName = 'Dialog'

export default Dialog
