<script setup lang="ts">
import { VueDraggable } from 'vue-draggable-plus'
import { useRoute } from 'vue-router'

const route = useRoute()
const dialogVisible = ref(false)
// search筛选的字段
const searchColumn = ref('')
// search筛选的options
const searchOptions: any = ref()

// 右侧箭头消失所需要translateX的值
const rightArrowHideDistance = ref(0)
// 控制tab栏的左右切换箭头
const handleTabArrow = () => {
  const parentElement: HTMLElement | null = document.querySelector('.left-all-columns')
  if (!parentElement) return

  // 左侧切换箭头
  const leftArrow: HTMLElement | null = parentElement.querySelector('.el-tabs__nav-prev')
  // 右侧切换箭头
  const rightArrow: HTMLElement | null = parentElement.querySelector('.el-tabs__nav-next')
  const targetObserverElement = parentElement.querySelector('.el-tabs__nav')

  if (!targetObserverElement || !leftArrow || !rightArrow) return

  // 创建一个函数来获取 translateX
  const getTranslateX = () => {
    const style = window.getComputedStyle(targetObserverElement)
    const matrix = style.transform

    if (matrix !== 'none' && matrix) {
      // 提取 matrix 中的 translateX 值
      const values = matrix.match(/matrix\(([^)]+)\)/)?.[1].split(', ')
      if (!values) return 0
      const translateX = parseFloat(values[4])
      return translateX
    }
    return 0 // 如果没有 transform 或 translateX，默认返回 0
  }

  // 检查并更新箭头显示状态
  const updateArrowVisibility = () => {
    const translateX = getTranslateX()
    if (translateX === 0) {
      leftArrow.style.display = 'none'
    } else {
      leftArrow.style.display = 'inline-block'
    }

    if (translateX === rightArrowHideDistance.value) {
      rightArrow.style.display = 'none'
    } else {
      rightArrow.style.display = 'inline-block'
    }
  }

  // 监听 transitionend 事件，等待动画结束后再获取 translateX 值
  targetObserverElement.addEventListener('transitionend', (event: any) => {
    if (event.propertyName === 'transform') {
      // 只有 transform 动画结束时才触发
      updateArrowVisibility()
    }
  })

  // 初次运行时手动检查一次
  updateArrowVisibility()
}

// 筛选选中时滚动到对应的元素
const handleDocumentClick = (event: any) => {
  if (!scrollTargetElement.value.contains(event.target)) {
    scrollTargetElement.value.className = scrollTargetElement.value.className.replace(
      'search-select-item',
      ''
    )
    scrollTargetElement.value = null
    document.removeEventListener('click', handleDocumentClick)
  }
}
const scrollTargetElement = ref()
const scrollToItem = (itemId: string) => {
  if (activeName.value !== 'All') {
    activeName.value = 'All'
  }
  setTimeout(() => {
    // 重置
    if (scrollTargetElement.value) {
      scrollTargetElement.value.className = scrollTargetElement.value.className.replace(
        'search-select-item',
        ''
      )
    }
    // 获取目标元素
    scrollTargetElement.value = document.querySelector(`[data-field='${itemId}']`)
    if (scrollTargetElement.value) {
      // 使用 scrollIntoView 滚动到该元素
      scrollTargetElement.value.scrollIntoView({ behavior: 'smooth', block: 'center' })
      scrollTargetElement.value.className += ' search-select-item'
      // 或者使用自定义滚动
      // const container = this.$refs.dataContainer
      // container.scrollTop = targetElement.offsetTop - container.offsetTop

      document.addEventListener('click', handleDocumentClick)
    }
  }, 100)
}

// 系统首次加载时，会有引导操作
let firstLoad = ref()
const step1 = ref()
const open1 = ref(false)
const isShowStep1 = ref(false)
const step2 = ref()
const open2 = ref(false)
const isShowStep2 = ref(false)
const handleCloseTour = (stepStr: string) => {
  if (stepStr === 'step1') {
    isShowStep1.value = false
    open1.value = false
  } else {
    isShowStep2.value = false
    open2.value = false
  }
  localStorage.setItem('firstLoadCustomizeColumns', 'true')
  // firstLoad = 'true'
}

// 左侧选中的tab
const activeName = ref()
// 分组列
const groupColumns: any = ref([])
// 所有数据
const allDataCopy: any = ref()

const loading = ref(false)
// 获取数据
const getData = async (reset?: string) => {
  loading.value = true
  let paramsData: any = { ...params.value.getData }
  if (reset === 'yes') {
    paramsData.reset = 'yes'
  }
  await $api.getTableSettingColumns(paramsData).then((res: any) => {
    if (res.code === 200) {
      // allDataCopy就是所有的数据
      allDataCopy.value = res.data.GroupColumnsAll
      groupColumns.value = res.data.GroupColumnsLeft
      activeName.value = allDataCopy.value?.[0]?.name
      searchOptions.value = res.data.GroupColumnsLeft?.[0]?.children
      // 右侧选中的数据
      selectColumns.value = res.data.GroupColumnsRight
      nextTick(() => {
        handleTabArrow()
        // 八秒后关闭引导
        if (!firstLoad.value) {
          setTimeout(() => {
            handleCloseTour('step1')
            handleCloseTour('step2')
          }, 8000)
        }
      })
    }
  })
  loading.value = false
}

const params = ref()
// rightDistance是右侧箭头消失所需要translateX的值
const openDialog = async (paramsData: Object, rightDistance: number) => {
  firstLoad.value = localStorage.getItem('firstLoadCustomizeColumns')
  params.value = paramsData
  dialogVisible.value = true
  await getData()
  rightArrowHideDistance.value = rightDistance
  nextTick(() => {
    if (!firstLoad.value) {
      open1.value = true
      isShowStep1.value = true
      open2.value = true
      isShowStep2.value = true
    }
  })
}

const selectColumns: any = ref([])

// 左侧Icon的显隐
const hoverAllIcon = ref('')
// 右侧Icon的显隐
const hoverSelectIcon = ref('')

const handleAddSelect = (item: any) => {
  groupColumns.value.forEach((groupItem: any) => {
    groupItem.children.forEach((child: any, index: number) => {
      if (child.field === item.field) {
        groupItem.children.splice(index, 1)
      }
    })
  })
  selectColumns.value.push(item)
}

// 从左侧拖拽到右侧时，删除其他分组中相同的数据
const handleLeftRemove = (e: any) => {
  if (e.to === e.from) return
  const curItem = e.data
  groupColumns.value.forEach((groupItem: any) => {
    groupItem.children.forEach((child: any, index: number) => {
      if (child.field === curItem.field) {
        groupItem.children.splice(index, 1)
      }
    })
  })
}

// 从右侧拖拽到左侧时，左侧根据分组添加数据
const handleRightRemove = (e: any) => {
  if (e.to === e.from) return
  const curItem = e.data
  // 获取当前移动项移入到了那一组
  const curGroup = groupColumns.value.find((item: any) => {
    return item.name == activeName.value
  })
  // 获取当前项应该对应哪一组
  const originalGroup = allDataCopy.value.find((item: any) => {
    if (item.name === 'All') {
      return false
    }
    const index = item.children.findIndex((child: any) => {
      return child.field === curItem.field
    })
    return index !== -1
  })

  if (curGroup.name !== originalGroup.name && curGroup.name !== 'All') {
    // 从当前分组中删除移入的数据
    curGroup.children.forEach((item: any, index: number) => {
      item.field === curItem.field && curGroup.children.splice(index, 1)
    })
    // 在对应分组中添加移入的数据
    groupColumns.value.forEach((item: any) => {
      item.name === originalGroup.name && item.children.push(curItem)
    })
    // 添加到All分组里
    groupColumns.value[0].children.push(curItem)
  } else if (curGroup.name === 'All') {
    // 在对应分组中添加移入的数据
    groupColumns.value.forEach((item: any) => {
      item.name === originalGroup.name && item.children.push(curItem)
    })
  } else if (curGroup.name === originalGroup.name) {
    groupColumns.value[0].children.push(curItem)
  }
}
// 点击右侧的减号删除选中的列，并添加到左侧
const handleDeleteSelect = (curItem: any) => {
  selectColumns.value.forEach((item: any, index: number) => {
    if (item.field === curItem.field) {
      selectColumns.value.splice(index, 1)
    }
  })
  // 获取当前项应该对应哪一组
  const originalGroup = allDataCopy.value.find((item: any) => {
    if (item.name === 'All') {
      return false
    }
    const index = item.children.findIndex((child: any) => {
      return child.field === curItem.field
    })
    return index !== -1
  })
  // 在对应分组中添加移入的数据
  groupColumns.value.forEach((item: any) => {
    item.name === originalGroup.name && item.children.push(curItem)
  })
  // 添加到All分组里
  groupColumns.value[0].children.push(curItem)
}

const handleMoveUpSelect = (item: any) => {
  const index = selectColumns.value.findIndex((i: any) => i.field === item.field)
  if (index === 0) return
  const temp = selectColumns.value[index]
  selectColumns.value[index] = selectColumns.value[index - 1]
  selectColumns.value[index - 1] = temp
}
const handleMoveDownSelect = (item: any) => {
  const index = selectColumns.value.findIndex((i: any) => i.field === item.field)
  if (index === selectColumns.value.length - 1) return
  const temp = selectColumns.value[index]
  selectColumns.value[index] = selectColumns.value[index + 1]
  selectColumns.value[index + 1] = temp
}

const emits = defineEmits<{
  customize: []
  reset: []
}>()
const handleReset = () => {
  getData('yes')
}
const handleApply = () => {
  const columnsList = selectColumns.value.map((item: any) => {
    return item.ids
  })
  $api
    .saveTableSettingColumns({
      ...params.value.saveData,
      ids: columnsList
    })
    .then((res: any) => {
      if (res.code === 200) {
        // ElMessage.success('Save successfully')
        emits('customize')
        dialogVisible.value = false
      }
    })
}

const clearData = () => {
  open1.value = false
  open2.value = false
  activeName.value = ''
  groupColumns.value = []
  selectColumns.value = []
  searchColumn.value = ''
}

defineExpose({
  openDialog
})
</script>

<template>
  <el-dialog
    class="customize-columns"
    v-model="dialogVisible"
    :width="1000"
    title="Customize Columns"
    @close="clearData"
  >
    <div class="search-header">
      <div class="search-input" ref="searchRef">
        <el-select
          v-model="searchColumn"
          @change="scrollToItem"
          filterable
          placeholder="Search columns you preffered"
        >
          <template #prefix>
            <span class="iconfont_icon">
              <svg class="iconfont" aria-hidden="true">
                <use xlink:href="#icon-icon_search_b"></use>
              </svg>
            </span>
          </template>
          <el-option
            v-for="item in searchOptions"
            :key="item.field"
            :label="item.label"
            :value="item.field"
          />
        </el-select>
      </div>
      <div class="tips">
        <span style="font-size: 16px">* </span>
        <span
          >Drag item over to this selection or click "add" icon to show the column on your
          {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list</span
        >
      </div>
    </div>
    <div class="draggable-list">
      <div class="left-all-columns" v-vloading="loading">
        <div class="tabs">
          <el-tabs v-model="activeName">
            <el-tab-pane
              v-for="groupItem in groupColumns"
              :key="groupItem.name"
              :label="groupItem.name"
              :name="groupItem.name"
            >
              <VueDraggable
                v-model="groupItem.children"
                class="column-list"
                :sort="false"
                ghost-class="ghost-column"
                :forceFallback="true"
                fallbackClass="fallback-class"
                group="customizeColumns"
                item-key="field"
                @end="handleLeftRemove"
              >
                <template v-for="(item, index) in groupItem.children" :key="item.field">
                  <div
                    :data-field="item.field"
                    class="column-item"
                    @mouseenter="hoverAllIcon = item.field"
                    @mouseleave="hoverAllIcon = ''"
                  >
                    <span class="font_family icon-icon_dragsort__b draggable-icon"></span>
                    <span class="title">{{ item.label }}</span>
                    <span
                      ref="step1"
                      v-if="hoverAllIcon === item.field || (index === 0 && isShowStep1)"
                      class="font_family icon-icon_add_b move-icon"
                      @click="handleAddSelect(item)"
                    ></span>
                  </div>
                </template>
              </VueDraggable>
            </el-tab-pane>
          </el-tabs>
        </div>
      </div>
      <div class="right-select-columns">
        <div class="title">
          Selected columns on your
          {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list
        </div>
        <VueDraggable
          v-vloading="loading"
          v-model="selectColumns"
          class="column-list"
          ghost-class="ghost-column"
          :forceFallback="true"
          fallback-class="fallback-class"
          group="customizeColumns"
          item-key="field"
          @end="handleRightRemove"
        >
          <template v-for="(item, index) in selectColumns" :key="item.field">
            <div
              class="column-item"
              @mouseenter="hoverSelectIcon = item.field"
              @mouseleave="hoverSelectIcon = ''"
            >
              <span
                class="font_family icon-icon_dragsort__b draggable-icon"
                style="font-size: 16px"
              ></span>
              <span class="title">{{ item.label }}</span>
              <span
                v-if="hoverSelectIcon === item.field || (index === 0 && isShowStep2)"
                class="font_family icon-icon_moveup_b move-icon"
                @click="handleMoveUpSelect(item)"
              ></span>
              <span
                v-if="hoverSelectIcon === item.field || (index === 0 && isShowStep2)"
                class="font_family icon-icon_movedown_b move-icon"
                @click="handleMoveDownSelect(item)"
              ></span>
              <span
                ref="step2"
                v-if="hoverSelectIcon === item.field || (index === 0 && isShowStep2)"
                class="font_family icon-icon_reduce_b move-icon"
                @click="handleDeleteSelect(item)"
              ></span>
            </div>
          </template>
        </VueDraggable>
      </div>
    </div>
    <template #footer>
      <el-button
        type="default"
        style="height: 40px; padding: 8px 40px"
        @click="dialogVisible = false"
        >Cancel</el-button
      >
      <el-button type="default" style="height: 40px; padding: 8px 20px" @click="handleReset"
        >Reset to default</el-button
      >
      <el-button
        class="el-button--dark"
        style="height: 40px; padding: 8px 40px"
        @click="handleApply"
      >
        Apply
      </el-button>
    </template>
    <el-tour
      :target-area-clickable="false"
      class="step1-tour"
      v-model="open1"
      :mask="false"
      type="primary"
      v-if="step1?.[0]"
    >
      <el-tour-step :show-close="false" :target="step1?.[0]">
        <template #default>
          <div class="description">
            <span>Drag</span> items to the right group or click the "<span>Add</span>" icon to add
            columns to the {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list.
          </div>
          <div class="got-it-text" @click="handleCloseTour('step1')">Got it</div>
        </template>
      </el-tour-step>
    </el-tour>
    <el-tour
      :target-area-clickable="false"
      class="step2-tour"
      v-model="open2"
      type="primary"
      :mask="false"
      v-if="step2?.[0]"
    >
      <el-tour-step :show-close="false" :target="step2?.[0]">
        <template #default>
          <div class="description">
            <span>Drag</span> items to the left group or click the "<span>Remove</span>" icon to
            delete columns from the
            {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list.
          </div>
          <div class="description">
            <span>Drag</span> items up or down to reorder the
            {{ route.path.includes('booking') ? 'booking' : 'shipment' }} list, or use the "<span
              >Move up</span
            >" and "<span>Move down</span>" icons.
          </div>
          <div class="got-it-text" @click="handleCloseTour('step2')">Got it</div>
        </template>
      </el-tour-step>
    </el-tour>
  </el-dialog>
</template>

<style lang="scss">
.customize-columns {
  .search-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    padding: 10px 0;

    .search-input {
      width: 50%;
      padding-right: 16px;
    }

    .tips {
      display: flex;
      align-items: flex-start;
      gap: 3px;
      width: 50%;
      padding-left: 5px;
      vertical-align: middle;

      span {
        font-size: 12px;
        color: var(--color-neutral-2);
      }
    }
  }

  .draggable-list {
    display: flex;
    user-select: none;
    gap: 8px;
  }
}

.right-select-columns,
.left-all-columns {
  width: 50%;

  .column-list {
    height: 400px;
    overflow: auto;

    .column-item {
      display: flex;
      align-items: center;
      height: 40px;
      margin-bottom: 5px;
      padding-left: 12px;
      border: 1px solid var(--color-border);
      border-radius: 6px;

      &:hover {
        background-color: #fff1e5;
        box-shadow: 4px 4px 32px 0px rgba(0, 0, 0, 0.1);
      }

      & > .title {
        flex: 1;
      }

      span.draggable-icon {
        margin-right: 12px;
        color: var(--color-neutral-3);
      }

      .font_family {
        font-size: 16px;
        cursor: pointer;
        margin-right: 16px;
      }

      .move-icon {
        &:hover {
          color: var(--color-theme);
        }
      }
    }
  }

  .ghost-column {
    opacity: 0;
    cursor: move !important;
  }

  .fallback-class {
    opacity: 1 !important;
    background-color: #fff1e5 !important;
    cursor: move !important;
  }
}

.left-all-columns {
  border: 1px solid var(--color-border);
  border-radius: 12px;

  .tabs {
    position: relative;
    height: 100%;

    .el-tabs {
      .el-tabs__header {
        margin-bottom: 0px;
        border-bottom: 1px solid #ebeef5;
      }

      .el-tabs__item {
        padding: 10px;
      }
    }
  }

  .column-list {
    padding: 8px;
    padding-bottom: 0px;
  }

  .search-select-item {
    border: 1px solid var(--color-theme) !important;
    box-shadow: 2px 2px 12px 0px rgba(237, 109, 0, 0.2);

    .title {
      color: var(--color-theme) !important;
    }
  }
}

.right-select-columns {
  background-color: #fffbf7;
  padding-top: 0;
  border: 1px dashed var(--color-border);
  border-radius: 12px;

  & > .title {
    height: 40px;
    padding: 8px;
    line-height: 24px;
    font-size: 16px;
    font-weight: 700;
  }

  .column-list {
    padding: 8px;
    padding-bottom: 0px;
  }

  .column-item {
    background-color: #fff;
  }
}
</style>
<style lang="scss">
.left-all-columns {
  .el-tabs__nav-prev,
  .el-tabs__nav-next {
    height: 40px;
    width: 40px;
  }

  .el-tabs__item {
    color: var(--color-neutral-1);
    font-weight: 400;
    font-size: 14px;
  }

  .el-tabs__item.is-active,
  .el-tabs__item:hover {
    font-weight: 700;
    font-size: 14px;
    color: var(--color-neutral-1);
  }

  .el-tabs__nav-prev {
    border-right: 1px solid var(--color-border);
    box-shadow: 1px 0px 10px rgba(0, 0, 0, 0.2);
    /* 左侧阴影 */
  }

  .el-tabs__nav-next {
    border-left: 1px solid var(--color-border);
    box-shadow: -1px 0px 10px rgba(0, 0, 0, 0.2);
    /* 左侧阴影 */
  }

  .el-tabs__nav-wrap {
    padding: 0 40px;
  }

  .el-tabs__item.is-active,
  .el-tabs__item:hover {
    color: var(--color-theme);
  }

  .el-tabs__active-bar {
    background-color: var(--color-theme);
  }
}

.search-header {
  & > .search-input {
    .el-select {
      width: 100%;

      .el-select__wrapper {
        border-radius: 20px;
      }
    }
  }
}
</style>

<style lang="scss">
.step1-tour {
  .el-tour__content {
    width: 240px;
    height: 124px;
    background-color: var(--color-theme);
    z-index: 9999 !important;
  }

  .el-tour__arrow {
    background-color: var(--color-theme);
  }

  .el-tour__footer {
    display: none;
  }
}

.step2-tour {
  .el-tour__content {
    width: 240px;
    height: 200px;
    background-color: var(--color-theme);
    z-index: 9999 !important;
  }

  .el-tour__arrow {
    background-color: var(--color-theme);
  }

  .el-tour__footer {
    display: none;
  }
}

.step1-tour,
.step2-tour {
  .el-tour__header {
    display: none;
  }

  .description {
    margin-bottom: 16px;
    color: white;
    line-height: 22px;

    span {
      color: white;
      font-weight: 600;
    }
  }

  .got-it-text {
    float: right;
    color: white;
    font-weight: 700;
    cursor: pointer;
  }
}
</style>
