<script lang="ts" setup>
import { computed, inject, ref } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'
import { TableContextKey } from './token'
import type { ColumnFixed, ColumnSettingItem } from './token'

defineOptions({
  name: 'ZmTableColumnSettingTree'
})

interface Props {
  modelValue: ColumnSettingItem[]
  parentKey?: string
  level?: number
}

const props = withDefaults(defineProps<Props>(), {
  level: 0
})

const emits = defineEmits<{
  'update:modelValue': [value: ColumnSettingItem[]]
}>()

const tableContext = inject(TableContextKey, {
  data: ref([]),
  loading: ref(false),
  columnAlign: ref('center' as const),
  columnMaxWidth: ref(360),
  columnSettings: ref([]),
  updateColumnVisible: () => {},
  updateColumnFixed: () => {},
  updateColumnOrder: () => {},
  resetColumnSettings: () => {}
})

const columnList = computed<ColumnSettingItem[]>({
  get: () => props.modelValue,
  set: (value) => {
    emits('update:modelValue', value)
  }
})

const dragHandleClass = computed(() => `column-setting-drag-handle-${props.level}`)
const dragHandleSelector = computed(() => `.${dragHandleClass.value}`)
const dragGroup = computed(() => ({
  name: `zm-table-column-setting-${props.parentKey || 'root'}`,
  pull: false,
  put: false
}))

const hasChildColumns = (item: ColumnSettingItem) => !!item.children?.length

const getVisibleTooltip = (item: ColumnSettingItem) => (item.visible ? '隐藏列' : '显示列')

const getFixedTooltip = (item: ColumnSettingItem, fixed: Exclude<ColumnFixed, false>) => {
  if (item.fixed === fixed) return fixed === 'left' ? '取消固定左侧' : '取消固定右侧'
  return fixed === 'left' ? '固定到左侧' : '固定到右侧'
}

const handleChildColumnOrder = (parentKey: string, children: ColumnSettingItem[]) => {
  tableContext.updateColumnOrder(
    children.map((item) => item.key),
    parentKey
  )
}

const toggleColumnFixed = (item: ColumnSettingItem, fixed: Exclude<ColumnFixed, false>) => {
  tableContext.updateColumnFixed(item.key, item.fixed === fixed ? false : fixed)
}
</script>

<template>
  <VueDraggable
    v-model="columnList"
    :animation="150"
    :handle="dragHandleSelector"
    :group="dragGroup"
    ghost-class="column-setting-ghost"
    class="column-setting-list"
    :class="{ 'is-root': level === 0, 'is-child-list': level > 0 }"
  >
    <div v-for="item in columnList" :key="item.key" class="column-setting-group">
      <div
        class="column-setting-item"
        :class="{ 'is-group': hasChildColumns(item), 'is-child': level > 0 }"
      >
        <button
          type="button"
          class="column-setting-icon-btn column-setting-drag-handle"
          :class="dragHandleClass"
          title="拖拽排序"
        >
          <div class="i-lucide:grip-vertical"></div>
        </button>
        <span class="column-setting-label" :title="item.label">
          {{ item.label }}
        </span>
        <el-tooltip
          :content="getVisibleTooltip(item)"
          placement="top"
          :show-after="500"
          :hide-after="0"
        >
          <button
            type="button"
            class="column-setting-icon-btn"
            :class="{ 'is-active': item.visible }"
            @click="tableContext.updateColumnVisible(item.key, !item.visible)"
          >
            <div :class="item.visible ? 'i-lucide:eye' : 'i-lucide:eye-off'"></div>
          </button>
        </el-tooltip>
        <el-tooltip
          :content="getFixedTooltip(item, 'left')"
          placement="top"
          :show-after="500"
          :hide-after="0"
        >
          <button
            type="button"
            class="column-setting-icon-btn"
            :class="{ 'is-active': item.fixed === 'left' }"
            @click="toggleColumnFixed(item, 'left')"
          >
            <div class="i-lucide:panel-left"></div>
          </button>
        </el-tooltip>
        <el-tooltip
          :content="getFixedTooltip(item, 'right')"
          placement="top"
          :show-after="500"
          :hide-after="0"
        >
          <button
            type="button"
            class="column-setting-icon-btn"
            :class="{ 'is-active': item.fixed === 'right' }"
            @click="toggleColumnFixed(item, 'right')"
          >
            <div class="i-lucide:panel-right"></div>
          </button>
        </el-tooltip>
      </div>

      <ZmTableColumnSettingTree
        v-if="item.children?.length"
        :model-value="item.children"
        :parent-key="item.key"
        :level="level + 1"
        @update:model-value="(children) => handleChildColumnOrder(item.key, children)"
      />
    </div>
  </VueDraggable>
</template>

<style scoped lang="scss">
.column-setting-list {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: var(--zm-table-column-setting-gap, 4px);

  &.is-root {
    max-height: var(--zm-table-column-setting-max-height, 360px);
    overflow-y: auto;
  }

  &.is-child-list {
    padding-left: 18px;
    margin: 3px 0 6px;
    border-left: 1px dashed var(--zm-table-column-setting-border-color, var(--el-border-color));
    gap: 3px;
  }
}

.column-setting-group {
  min-width: 0;
}

.column-setting-item {
  display: grid;
  height: var(--zm-table-column-setting-row-height, 32px);
  min-width: 0;
  padding: 0 4px;
  font-size: var(--zm-table-column-setting-font-size, 12px);
  font-weight: var(--zm-table-column-setting-item-font-weight, 400);
  color: var(--zm-table-column-setting-text-color, var(--el-text-color-regular));
  border-radius: var(--zm-table-column-setting-radius, 6px);
  align-items: center;
  column-gap: 6px;
  grid-template-columns: 22px minmax(0, 1fr) repeat(3, 24px);

  &:hover {
    background: var(--zm-table-column-setting-hover-bg, var(--el-fill-color-lighter));
  }

  &.is-group {
    font-weight: var(--zm-table-column-setting-group-font-weight, 600);
  }

  &.is-child {
    height: var(--zm-table-column-setting-child-row-height, 30px);
    padding-left: 2px;
  }
}

.column-setting-label {
  overflow: hidden;
  color: currentcolor;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.column-setting-icon-btn {
  display: flex;
  width: var(--zm-table-column-setting-icon-btn-size, 22px);
  height: var(--zm-table-column-setting-icon-btn-size, 22px);
  padding: 0;
  color: var(--zm-table-column-setting-icon-color, #8aa0b8);
  cursor: pointer;
  background: transparent;
  border: 0;
  border-radius: 4px;
  align-items: center;
  justify-content: center;

  &:hover,
  &.is-active {
    color: var(--zm-table-column-setting-icon-active-color, var(--el-color-primary));
    background-color: var(
      --zm-table-column-setting-icon-active-bg,
      var(--el-color-primary-light-9)
    );
  }

  > div {
    width: var(--zm-table-column-setting-icon-size, 15px);
    height: var(--zm-table-column-setting-icon-size, 15px);
  }
}

.column-setting-drag-handle {
  cursor: grab;

  &:active {
    cursor: grabbing;
  }
}

.column-setting-ghost {
  background: var(--zm-table-column-setting-ghost-bg, var(--el-color-primary-light-9));
  opacity: var(--zm-table-column-setting-ghost-opacity, 0.55);
}
</style>
