import { shallowRef, defineAsyncComponent, Component } from 'vue'
import { useRoute } from 'vue-router'
import { findTreeNodeById } from '@/filters'
import { AuthType } from '@/constants/menu'
import { useRouterStore } from '@/stores'
import { OperationOptions } from './types'

export function useOperation<T>({ code, onClose }: OperationOptions = {}) {
    const route = useRoute()
    const routerStore = useRouterStore()
    const routeName = code ?? String(route.name)

    const menus = findTreeNodeById(routerStore.userRoutes, routeName, { id: 'resourceCode' })
    const buttons: Model.MenusRsp[] = []
    const componentMap = new Map<string, Component>()
    const componentId = shallowRef<string>()
    const record = shallowRef<T>()

    menus?.children?.forEach((item) => {
        if (item.authType === AuthType.Operate && item.show && item.component) {
            const componentString = item.component.replace(/^\/+/, '') // 过滤字符串前面所有 '/' 字符
            const componentPath = componentString.replace(/\.\w+$/, '') // 过滤后缀名，为了让 import 加入 .vue ，不然会有警告提示...
            const asyncComponent = defineAsyncComponent({
                loader: () => import('/' + process.env.VUE_APP_ROOT + componentPath + '.vue'),
            })
            componentMap.set(item.resourceCode, asyncComponent)
            buttons.push(item)
        }
    })

    // 获取按钮组
    const getActionButtons = (filtered?: string[], reverse?: boolean) => {
        if (filtered?.length) {
            return buttons.filter((item) => filtered.includes(item.resourceCode) === !reverse)
        }
        return buttons
    }

    // 打开组件
    const openComponent = (id: string, row?: T) => {
        record.value = row
        componentId.value = id
    }

    // 关闭组件
    const closeComponent = (triggerEvent: boolean) => {
        if (triggerEvent && onClose) {
            onClose(componentId.value ?? '')
        }
        componentId.value = undefined
    }

    return {
        componentMap,
        componentId,
        record,
        openComponent,
        closeComponent,
        getActionButtons
    }
}