import {
  forwardRef,
  ReactNode,
  ForwardRefExoticComponent,
  useImperativeHandle,
  CSSProperties,
} from 'react'
import classNames from 'classnames'
import { Popup, PopupProps } from '../popup/Popup'
import { Button, ButtonProps } from '../button/Button'
import { Icon } from '../icon/Icon'
import { show, alert, confirm } from './DialogImperative'
import { CommonComponentProps } from '../../utils/types'
import './Dialog.scss'
import { useEvent } from '../../use'

const CANCEL = 'cancel'
const CONFIRM = 'confirm'

type CloseType = 'cancel' | 'confirm'

export interface DialogRef {
  clear: () => void
  reset: () => void
}

type DialogButtonType = 'rounded' | 'text'

export interface DialogProps extends CommonComponentProps {
  className?: string
  style?: CSSProperties
  children?: ReactNode
  maskClosable?: boolean
  title?: ReactNode
  message?: ReactNode
  header?: ReactNode
  headed?: boolean
  footer?: ReactNode
  buttonType?: DialogButtonType
  showCancel?: boolean
  cancelText?: ReactNode
  cancelProps?: ButtonProps
  showConfirm?: boolean
  confirmText?: ReactNode
  confirmProps?: ButtonProps
  onCancel?: () => void
  onConfirm?: () => void
  beforeClose?: (done: () => void, type: CloseType) => void
  onDone?: () => void
  visible?: boolean
  popupProps?: PopupProps
}

export interface Dialog extends ForwardRefExoticComponent<DialogProps> {
  show: (props: DialogProps) => any
  alert: (props: DialogProps) => any
  confirm: (props: DialogProps) => any
}

export interface DialogImperative {}

const buttonProps: {
  [p in DialogButtonType]: {
    [p in 'cancel' | 'confirm']: ButtonProps
  }
} = {
  text: {
    cancel: {
      type: 'text',
      theme: 'secondary',
      size: 'large',
    },
    confirm: {
      type: 'text',
      theme: 'primary',
      size: 'large',
    },
  },
  rounded: {
    cancel: {
      type: 'secondary',
      theme: 'primary',
      rounded: true,
    },
    confirm: {
      type: 'primary',
      theme: 'primary',
      rounded: true,
    },
  },
}

export const Dialog = forwardRef<DialogImperative, DialogProps>(
  (props, ref) => {
    const {
      className,
      children,
      maskClosable = false,
      title,
      message,
      header,
      footer,
      buttonType = 'text',
      headed,
      showCancel = false,
      cancelText = '取消',
      cancelProps,
      showConfirm = true,
      confirmText = '确定',
      confirmProps,
      onCancel,
      onConfirm,
      beforeClose,
      onDone,
      visible = false,
      popupProps = {},
      ...restProps
    } = props

    const {
      mask = true,
      placement = 'center',
      onMaskClick,
      ...restPopupProps
    } = popupProps

    const handleMaskClick = useEvent(() => {
      if (maskClosable) {
        onCancel?.()
      }
      onMaskClick?.()
    })

    const handleClose = () => {
      perhapsClose(CANCEL, onCancel)
    }
    const handleCancel = () => {
      perhapsClose(CANCEL, onCancel)
    }
    const handleConfirm = () => {
      perhapsClose(CONFIRM, onConfirm)
    }

    const perhapsClose = (
      type: CloseType,
      callback: (() => void) | undefined
    ) => {
      if (beforeClose) {
        beforeClose(() => {
          onDone?.()
          callback?.()
        }, type)
      } else {
        callback?.()
      }
    }

    useImperativeHandle(ref, () => ({}))

    const dialogClass = classNames(
      's-dialog',
      {
        's-dialog-headed': headed,
        's-dialog-untitled': !title,
        's-dialog-rounded-button': buttonType === 'rounded',
      },
      className
    )

    const renderTitle = () => {
      return <div className="s-dialog-title">{title}</div>
    }

    return (
      <Popup
        {...restPopupProps}
        visible={visible}
        placement={placement}
        mask={mask}
        onMaskClick={handleMaskClick}
      >
        <div {...restProps} className={dialogClass}>
          {headed && (
            <div className="s-dialog-header">
              {header || renderTitle()}

              <Button
                className="s-dialog-close"
                type="pale-text"
                theme="secondary"
                size="large"
                onClick={handleClose}
              >
                <Icon prefix="si" name="close"></Icon>
              </Button>
            </div>
          )}
          <div className="s-dialog-body">
            {children || (
              <>
                {!headed && title && renderTitle()}
                {message && <div className="s-dialog-message">{message}</div>}
              </>
            )}
          </div>
          <div className="s-dialog-footer">
            {footer || (
              <>
                {showCancel && (
                  <Button
                    {...buttonProps[buttonType].cancel}
                    className="s-dialog-button s-dialog-cancel"
                    {...cancelProps}
                    onClick={handleCancel}
                  >
                    {cancelText}
                  </Button>
                )}
                {showConfirm && (
                  <Button
                    {...buttonProps[buttonType].confirm}
                    className="s-dialog-button s-dialog-confirm"
                    {...confirmProps}
                    onClick={handleConfirm}
                  >
                    {confirmText}
                  </Button>
                )}
              </>
            )}
          </div>
        </div>
      </Popup>
    )
  }
) as Dialog

Dialog.show = show
Dialog.alert = alert
Dialog.confirm = confirm

export default Dialog
