import React, {
  useRef,
  useMemo,
  memo,
  forwardRef,
  useCallback,
  useState,
  useImperativeHandle,
  useId
} from 'react'
import { Modal, Form } from 'antd'
import type { ModalProps } from 'antd'

const MyModal = memo(
  forwardRef((prop: any, ref) => {
    const [form] = Form.useForm()
    const [modalChildren, setModalChildren] = useState<React.ReactElement>(null)
    const [loading, setLoading] = useState(false)
    const [modalProps, setModalProps] = useState<ModalProps>({
      visible: false
    })
    const typeRef = useRef<string>()

    const onFinish = useCallback(
      (values: any) => {
        const response = modalProps.onOk?.(values)

        if (response instanceof Promise) {
          setLoading(true)

          response.finally(() => {
            setLoading(false)
          })
        }
      },
      [form, modalProps]
    )
    // ant.design 4.0 Form的onFinish触发回调
    // const onFinish = useCallback(
    //   (values: any) => {
    //     modalProps.onOk?.(values)
    //   },
    //   [form, modalProps]
    // )

    // 关闭当前Modal
    const onClose = useCallback(() => {
      setModalProps(source => ({
        ...source,
        visible: false
      }))
    }, [form])

    // 关闭当前Modal
    const onOpen = useCallback(() => {
      setModalProps(source => ({
        ...source,
        visible: true
      }))
    }, [form])

    useImperativeHandle(
      ref,
      () => ({
        // 注入Modal的子组件
        injectChildren: element => {
          setModalChildren(element)
        },
        // 注入Modal参数
        injectModalProps: props => {
          setModalProps(source => {
            return {
              ...source,
              ...props
            }
          })
        },
        // 打开Modal
        open: () => {
          onOpen()
        },
        // 关闭Modal
        close: () => {
          if (loading) setLoading(false)
          onClose()
        },
        // 设置表单数据
        setFieldsValue: (values: any) => {
          form.setFieldsValue?.(values)
        },
        setType: (type: string) => {
          typeRef.current = type
        }
      }),
      []
    )

    const handleOk = useCallback(() => {
      if (typeRef.current === 'form') {
        form.submit()
      } else {
        modalProps.onOk?.(null)
      }
    }, [form, modalProps])

    // 这里的Modal是ant.design中的Modal
    return (
      <Modal {...modalProps} onCancel={onClose} onOk={handleOk} okButtonProps={{ loading }} destroyOnClose>
        {modalChildren
          ? React.cloneElement(modalChildren, {
              onFinish,
              form,
              onClose
            })
          : null}
      </Modal>
    )
  })
)

interface modalRefType {
  open: () => void
  close: () => void
  injectChildren: (child: React.ReactElement) => void
  injectModalProps: (props: ModalProps) => void
  setFieldsValue: (values: any) => void
  setType: (type: string) => void
}

interface OpenArgType extends ModalProps {
  children?: React.ReactElement
  type?: 'form' | 'default'
  initialValues?: {
    [key: string]: any
  }
}

/**
 * 适用于单弹窗模式
 */
const useModal = () => {
  const modalRef = useRef<modalRefType>()
  const handle = useMemo(() => {
    return {
      open: ({ children, type, initialValues, ...rest }: OpenArgType) => {
        modalRef.current.setType(type)
        modalRef.current.injectChildren(children) // 注入子组件
        modalRef.current.injectModalProps(rest) // 注入Modal的参数
        modalRef.current.open()

        if (initialValues && type === 'form') {
          modalRef.current.setFieldsValue?.(initialValues)
        }
      },
      close: () => {
        modalRef.current.close()
      }
    }
  }, [])

  return [handle, <MyModal ref={modalRef} key={useId()} />] as const
}

export type ModalAction = {
  open: (args: OpenArgType) => void
  close: () => void
}

export default useModal
