import {
  ref,
  defineAsyncComponent,
  getCurrentInstance,
  computed,
  h,
  createApp,
  unref,
  provide,
  reactive
} from 'vue'
import type { Component, App, VNode, ComputedRef } from 'vue'
import type { ElDialog } from 'element-plus'

import Dialog from '@/components/Dialog/index.vue'

import { DialogProps, DialogModalProps } from './props'

const defaultModalProps: Omit<DialogModalProps, 'content'> = {
  title:'',
  showOk: true,
  showClose: false,
  hideCancel: false,
  okText: '确定',
  cancelText: '取消',
  footer: true,
  header: true,
  width: '60%'
}

/**
 * 获取组件实例的 provides
 * @param instance Vue 组件实例
 * @returns 组件实例及其父级的 provides 对象
 */
function getProvides(instance: any): Record<string, any> {
  let provides = instance?.provides || {}
  if (instance.parent) {
    provides = { ...provides, ...getProvides(instance.parent) }
  }
  return provides
}

const useDialog = (initialOptions: DialogProps) => {
  const modalRef = ref<InstanceType<typeof ElDialog> | null>(null)
  const currentInstance = getCurrentInstance() as any
  const provides = getProvides(currentInstance)
  // 用于保存对话框应用实例和可见性状态
  let dialogApp: App | null = null
  const visible = ref(false)
  let container: HTMLElement | null = null

  // 使用reactive存储options，以便能够响应式更新
  const options = reactive<DialogProps>({
    ...initialOptions
  })

  const mergeModalOptions: ComputedRef<DialogModalProps> = computed(() => {
    return {
      ...defaultModalProps,
      ...options.modalProps
    }
  })

  const openModal = () => {
    // 判断content类型
    const isAsync = typeof options.content === 'function'
    const isString = typeof options.content === 'string'

    const modalComponent = isAsync
      ? defineAsyncComponent(options.content as () => Promise<Component>)
      : isString
        ? h('div', options.content as string)
        : options.content

    container = document.createElement('div')
    document.body.appendChild(container)

    // 状态管理
    visible.value = true

    dialogApp = createApp({
      setup() {
        const closed = () => {
          if (dialogApp) {
            dialogApp.unmount()
            dialogApp = null
          }
          if (container) {
            container.remove()
            container = null
          }
        }

        const instance = getCurrentInstance() as any

        if (instance) {
          instance.provides = { ...instance.provides, ...provides }

          // 使用provide提供上下文
          provide('parentInstance', currentInstance)
          provide('dialogInstance', instance)
          provide('dialogProvides', provides)
        }



        const onOk = async () => {
          // 调用props中传递的onOk回调函数
          try {
            await unref(options.modalProps)?.onOk?.();
            // 如果需要，可以在这里添加默认的关闭行为
          } catch (error) {
            console.error('Dialog onOk error:', error);
          }
        }

        return () => {
          return h(
            Dialog,
            {
              ...unref(mergeModalOptions),
              modelValue: visible.value,
              'onUpdate:modelValue': (val: boolean) => {
                visible.value = val
              },
              onOk: onOk,
              onClosed: () => {
                
                //如果需要回调就调用回调
                unref(options.contentProps)?.onClosed?.()
                closed()
              }
            },
            () =>
              h(modalComponent, {
                ...options.contentProps,
                // 将当前实例上下文传递给子组件
                instance: instance,
                // 传递provides
                provides: provides,
                // 如果需要，还可以传递其他上下文信息
                parentContext: currentInstance
              })
          )
        }
      }
    })
    // 挂载应用
    dialogApp.mount(container)
  }

  const closeModal = () => {
    // 设置可见性为false，触发对话框关闭
    if (unref(visible)) {
      visible.value = false
    }

    // 如果dialogApp存在，手动卸载
    if (dialogApp) {
      setTimeout(() => {
        dialogApp?.unmount()
        dialogApp = null

        if (container) {
          container.remove()
          container = null
        }
      }, 300) // 给动画效果一些时间
    }
  }

  //更新属性
  const updateModalProps = (props: Partial<DialogProps>) => {
    if (!dialogApp) {
      return false
    }

    // 更新modalProps
    if (props.modalProps) {
      options.modalProps = {
        ...options.modalProps,
        ...props.modalProps
      }
    }

    // 更新contentProps
    if (props.contentProps) {
      options.contentProps = {
        ...options.contentProps,
        ...props.contentProps
      }
    }

    // 如果提供了新的content，需要重新打开对话框
    if (props.content) {
      options.content = props.content
      closeModal()
      setTimeout(() => {
        openModal()
      }, 300)
    }

    return true
  }

  return {
    modalRef: modalRef,
    openModal: openModal,
    closeModal: closeModal,
    updateModalProps: updateModalProps
  }
}

export default useDialog
