<template>
    <div class="tabs-box">
        <div class="tabs-menu">
            <el-tabs v-model="tabsMenuValue" type="card" @tab-click="tabClick" @tab-remove="tabRemove">
                <el-tab-pane
                    v-for="item in tabsMenuList"
                    :key="item.path"
                    :label="item.title"
                    :name="item.path"
                    :closable="item.close"
                >
                    <template #label>
                        <el-icon v-show="item.icon && tabsIcon" class="tabs-icon">
                            <component :is="item.icon"></component>
                        </el-icon>
                        {{ item.title }}
                    </template>
                </el-tab-pane>
            </el-tabs>
            <MoreButton />
        </div>
    </div>
</template>

<script setup lang="ts">
import Sortable from 'sortablejs'
import { computed, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import type { TabPaneName, TabsPaneContext } from 'element-plus'
import { HOME_URL } from '@/config'
import { useGlobalStore } from '@/stores/modules/global'
import { useTabsStore } from '@/stores/modules/tabs'
import MoreButton from './components/MoreButton.vue'

defineOptions({
    name: 'LayoutTabs'
})

const route = useRoute()
const router = useRouter()
const tabStore = useTabsStore()
const globalStore = useGlobalStore()

const tabsMenuValue = ref(route.fullPath)
const tabsMenuList = computed(() => tabStore.tabsMenuList)
const tabsIcon = computed(() => globalStore.tabsIcon)

const resolveCurrentTabPath = () => {
    const parentPath = route.meta.parentPath as string | undefined
    return route.meta.hideTab ? parentPath || route.fullPath : route.fullPath
}

onMounted(() => {
    tabsDrop()
    initTabs()
})

const ensureParentTab = () => {
    const parentPath = resolveCurrentTabPath()
    if (!parentPath || tabStore.tabsMenuList.some(item => item.path === parentPath)) return

    const parentRoute = router.getRoutes().find(item => item.path === parentPath && item.name)
    if (!parentRoute) return

    // 直接打开隐藏子页时补齐父级主标签
    tabStore.addTabs({
        icon: parentRoute.meta.icon as string,
        title: parentRoute.meta.title as string,
        path: parentRoute.path,
        name: parentRoute.name as string,
        close: !parentRoute.meta.isAffix,
        isKeepAlive: parentRoute.meta.isKeepAlive as boolean
    })
}

watch(
    () => route.fullPath,
    () => {
        if (route.meta.isFull) return
        if (route.meta.hideTab) {
            ensureParentTab()
            tabsMenuValue.value = resolveCurrentTabPath()
        } else {
            tabsMenuValue.value = route.fullPath
            const tabsParams = {
                icon: route.meta.icon as string,
                title: route.meta.title as string,
                path: route.fullPath,
                name: route.name as string,
                close: !route.meta.isAffix,
                isKeepAlive: route.meta.isKeepAlive as boolean
            }
            tabStore.addTabs(tabsParams)
        }
    },
    { immediate: true }
)

const initTabs = () => {
    const affixTabs = router
        .getRoutes()
        .filter(item => item.meta.isAffix && !item.meta.isHide && !item.meta.isFull && item.name && item.path)
        .sort((a, b) => {
            if (a.path === HOME_URL) return -1
            if (b.path === HOME_URL) return 1
            return 0
        })

    for (let index = affixTabs.length - 1; index >= 0; index -= 1) {
        const item = affixTabs[index]
        const tabsParams = {
            icon: item.meta.icon as string,
            title: item.meta.title as string,
            path: item.path,
            name: item.name as string,
            close: !item.meta.isAffix,
            isKeepAlive: item.meta.isKeepAlive as boolean,
            unshift: true
        }
        tabStore.addTabs(tabsParams)
    }
}

const tabsDrop = () => {
    Sortable.create(document.querySelector('.el-tabs__nav') as HTMLElement, {
        draggable: '.el-tabs__item',
        animation: 300,
        onEnd({ newIndex, oldIndex }) {
            const tabsList = [...tabStore.tabsMenuList]
            const currRow = tabsList.splice(oldIndex as number, 1)[0]
            tabsList.splice(newIndex as number, 0, currRow)
            tabStore.setTabs(tabsList)
        }
    })
}

const tabClick = (tabItem: TabsPaneContext) => {
    const fullPath = tabItem.props.name as string
    router.push(fullPath)
}

const tabRemove = (fullPath: TabPaneName) => {
    tabStore.removeTabs(fullPath as string, fullPath === tabsMenuValue.value)
}
</script>

<style scoped lang="scss">
@use './index.scss';
</style>
