<script setup>
import { useTabsViewStore } from '@/stores/TabsViewStore'
import { useRoute, useRouter } from 'vue-router'
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { isString } from 'lodash-es'
import TabsViewItem from '@/components/common-tabs-view/tabs-view-item.vue'
import { toGetParams } from '@/utils'
import { isNestedRoute } from '@/route/RouteUtils'
import { useGetDerivedNamespace } from 'element-plus'
import Sortable from 'sortablejs'

const router = useRouter()
const route = useRoute()
const tabsViewStore = useTabsViewStore()
const tabRef = ref()
let sortable = null
watch(route, () => {
  if (route.path) {
    tabsViewStore.addHistoryTab(route)
    tabsViewStore.currentTab = route.path
  }
}, { immediate: true })

onMounted(() => {
  if (!tabsViewStore.historyTabs.length) {
    tabsViewStore.addHistoryTab(route)
  }
  tabsViewStore.currentTab = route.path
  if (tabRef.value?.tabNavRef) {
    const ns = useGetDerivedNamespace().value
    const { tabListRef } = tabRef.value.tabNavRef
    sortable = new Sortable(tabListRef, {
      animation: 150,
      draggable: `.${ns}-tabs__item`,
      filter: '.is-disabled',
      onEnd (event) {
        const { oldIndex, newIndex } = event
        tabsViewStore.reIndexHistoryTab(oldIndex, newIndex)
      }
    })
  }
})

const selectHistoryTab = path => {
  const tab = isString(path) ? tabsViewStore.findHistoryTab(path) : path
  if (tab) {
    router.push(tab)
    if (!isNestedRoute(tab)) {
      tabsViewStore.addCachedTab(tab)
    }
  }
}

const removeHistoryTab = path => {
  const lastTab = tabsViewStore.removeHistoryTab({ path })
  if (lastTab) {
    selectHistoryTab(lastTab)
  }
}

const refreshHistoryTab = tab => {
  const time = new Date().getTime()
  const query = Object.assign({}, tab.query, { _t: time })
  router.replace(`${tab.path}?${toGetParams(query)}`)
  if (!isNestedRoute(tab)) {
    tabsViewStore.addCachedTab(tab)
  }
}

const removeOtherHistoryTabs = tab => {
  tabsViewStore.removeOtherHistoryTabs(tab)
  selectHistoryTab(tab.path)
}

const removeHistoryTabs = (tab, type) => {
  tabsViewStore.removeHistoryTabs(tab, type)
  selectHistoryTab(tab.path)
}

const tabItems = ref()
const onDropdownVisibleChange = (visible, tab) => {
  if (visible) {
    tabItems.value.forEach(({ dropdownRef }) => {
      if (dropdownRef.id !== tab.path) {
        dropdownRef.handleClose()
      }
    })
  }
}
onBeforeUnmount(() => {
  sortable?.destroy()
  sortable = null
})

</script>

<template>
  <el-tabs
    ref="tabRef"
    v-bind="$attrs"
    v-model="tabsViewStore.currentTab"
    class="common-tabs"
    type="card"
    :closable="tabsViewStore.historyTabs.length>1"
    @tab-change="selectHistoryTab"
    @tab-remove="removeHistoryTab"
  >
    <tabs-view-item
      v-for="item in tabsViewStore.historyTabs"
      ref="tabItems"
      :key="item.path"
      :tab-item="item"
      :label-config="item.labelConfig"
      @refresh-history-tab="refreshHistoryTab"
      @remove-other-history-tabs="removeOtherHistoryTabs"
      @remove-history-tabs="removeHistoryTabs"
      @on-dropdown-visible-change="onDropdownVisibleChange"
      @remove-history-tab="removeHistoryTab"
    />
  </el-tabs>
</template>

<style scoped>
:deep(.el-tabs__header) {
  margin: 0;
  border-bottom: 1px solid var(--el-border-color-light) !important;
  position: relative;
}

:deep(.el-tabs__nav) {
  border: 0 !important;
}

/* Allow pseudo-elements to overflow and cover the header border */
:deep(.el-tabs__nav-wrap),
:deep(.el-tabs__nav-scroll) {
  overflow: visible !important;
}

:deep(.el-tabs__item) {
  border: 1px solid transparent !important;
  margin: 0 4px 0 0;
  border-radius: 4px 4px 0 0;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  /* Default inactive background */
  background-color: var(--el-fill-color-light);
}

/* Bottom border for inactive tabs */
:deep(.el-tabs__item:not(.is-active)) {
  border-bottom: 1px solid var(--el-border-color-light) !important;
}

/* Specific styling for active tab to look "connected" to content */
:deep(.el-tabs__item.is-active) {
  background-color: var(--el-bg-color);
  border-left: 1px solid var(--el-border-color-light) !important;
  border-right: 1px solid var(--el-border-color-light) !important;
  border-top: 1px solid var(--el-border-color-light) !important;
  border-bottom: 1px solid transparent !important;
  position: relative;
  font-weight: 600;
}

/* Cover the header bottom border under active tab */
:deep(.el-tabs__item.is-active)::before {
  content: "";
  position: absolute;
  bottom: -2px;
  left: 0;
  right: 0;
  height: 4px;
  background-color: var(--el-bg-color);
  z-index: 10;
}

/* Top highlight line for active tab */
:deep(.el-tabs__item.is-active)::after {
  content: "";
  position: absolute;
  top: -1px;
  left: -1px;
  width: calc(100% + 2px);
  height: 2px;
  background-color: var(--el-color-primary);
  border-radius: 4px 4px 0 0;
}

:deep(.el-tabs__item:not(.is-active):hover) {
  background-color: var(--el-fill-color);
  color: var(--el-color-primary);
}

/* Dark mode adjustments */
.dark :deep(.el-tabs__header) {
  border-bottom: 1px solid var(--el-border-color-darker) !important;
}

.dark :deep(.el-tabs__item) {
  background-color: var(--el-bg-color-overlay);
}

.dark :deep(.el-tabs__item:not(.is-active)) {
  border-bottom: 1px solid var(--el-border-color-darker) !important;
}

.dark :deep(.el-tabs__item.is-active) {
  background-color: var(--el-bg-color);
  border-color: var(--el-border-color-darker) !important;
  border-bottom-color: transparent !important;
}

.dark :deep(.el-tabs__item.is-active)::before {
  background-color: var(--el-bg-color);
}
</style>
