<script lang="ts" setup>
import { defaultProps, handleTree } from '@/utils/tree'
import { ElTree } from 'element-plus'
import * as DeptApi from '@/api/system/dept'
import { Search, CaretLeft, CaretRight } from '@element-plus/icons-vue'

interface Tree {
  id: number
  name: string
  children?: Tree[]
  sort?: number
}

type RequestApi = 'specifiedSimpleDepts' | 'getSimpleDeptList'

const props = defineProps({
  deptId: { type: Number, required: true },
  modelValue: { type: Number, default: undefined },
  topId: { type: Number, required: true },
  title: { type: String, default: '部门' },
  initSelect: { type: Boolean, default: true },
  showTitle: { type: Boolean, default: true },
  requestApi: {
    type: String as PropType<RequestApi>,
    default: 'specifiedSimpleDepts'
  }
})

const emits = defineEmits(['update:modelValue', 'node-click'])

// --- 状态控制 ---
const isCollapsed = ref(false)
const deptName = ref('')
const deptList = ref<Tree[]>([])
const treeRef = ref<InstanceType<typeof ElTree>>()
const expandedKeys = ref<number[]>([])

// --- 逻辑处理 (保持不变) ---
const sortTreeBySort = (treeNodes: Tree[]) => {
  if (!treeNodes || !Array.isArray(treeNodes)) return treeNodes
  const sortedNodes = [...treeNodes].sort((a, b) => (a.sort ?? 999999) - (b.sort ?? 999999))
  sortedNodes.forEach((node) => {
    if (node.children) node.children = sortTreeBySort(node.children)
  })
  return sortedNodes
}

const resolveFallbackId = (depts: Tree[], preferredId: number) => {
  if (depts.some((item) => item.id === preferredId)) return preferredId
  if (depts.some((item) => item.id === props.topId)) return props.topId
  return depts[0]?.id
}

const loadDeptData = async () => {
  if (props.requestApi === 'getSimpleDeptList') {
    const depts = (await DeptApi.getSimpleDeptList()) as Tree[]
    return {
      depts,
      currentId: resolveFallbackId(depts, props.deptId)
    }
  }

  let id = props.deptId
  if (id !== props.topId) {
    const depts = await DeptApi.specifiedSimpleDepts(props.topId)
    if (depts.length && !depts.find((item) => item.id === props.deptId)) id = props.topId
  }
  const depts = (await DeptApi.specifiedSimpleDepts(id)) as Tree[]
  return {
    depts,
    currentId: id
  }
}

const loadTree = async () => {
  try {
    const { depts, currentId } = await loadDeptData()
    const targetKey = props.modelValue ?? (props.initSelect ? currentId : null)
    if (props.initSelect && props.modelValue) {
      emits('update:modelValue', currentId)
    }
    if (targetKey && !expandedKeys.value.includes(targetKey)) {
      expandedKeys.value = [...expandedKeys.value, targetKey]
    }
    deptList.value = sortTreeBySort(handleTree(depts))
    nextTick(() => {
      if (targetKey && treeRef.value) {
        treeRef.value.setCurrentKey(targetKey)
      }
    })
  } catch (e) {
    console.error(e)
  }
}

const handleNodeClick = (data: Tree) => {
  emits('update:modelValue', data.id)
  emits('node-click', data)
}

const filterNode = (val: string, data: Tree) => !val || data.name.includes(val)

watch(deptName, (val) => treeRef.value?.filter(val))
watch(() => [props.deptId, props.topId, props.requestApi], loadTree)
watch(
  () => props.modelValue,
  (val) => {
    if (val && treeRef.value) treeRef.value.setCurrentKey(val)

    if (val && !expandedKeys.value.includes(val)) {
      expandedKeys.value.push(val)
    }
  },
  { immediate: true }
)

onMounted(loadTree)
</script>

<template>
  <div
    class="dept-aside-container relative bg-white dark:bg-[#1d1e1f] shadow rounded-lg transition-all duration-300 ease-in-out overflow-visible"
    :class="[isCollapsed ? 'is-collapsed' : 'p-4']">
    <div v-show="!isCollapsed" class="h-full flex flex-col gap-4 overflow-hidden w-full">
      <h1 v-if="showTitle" class="text-lg font-medium truncate shrink-0">{{ props.title }}</h1>

      <div class="shrink-0">
        <el-input
          v-model="deptName"
          placeholder="请输入部门名称"
          clearable
          size="default"
          :prefix-icon="Search" />
      </div>

      <div class="flex-1 relative overflow-hidden">
        <el-auto-resizer class="absolute">
          <template #default="{ height }">
            <el-scrollbar :style="{ height: `${height}px` }">
              <el-tree
                ref="treeRef"
                :data="deptList"
                :props="defaultProps"
                :expand-on-click-node="false"
                :filter-node-method="filterNode"
                node-key="id"
                highlight-current
                :default-expanded-keys="expandedKeys"
                @node-click="handleNodeClick" />
            </el-scrollbar>
          </template>
        </el-auto-resizer>
      </div>
    </div>

    <div class="collapse-handle" @click="isCollapsed = !isCollapsed">
      <el-icon size="12">
        <CaretLeft v-if="!isCollapsed" />
        <CaretRight v-else />
      </el-icon>
    </div>
  </div>
</template>

<style scoped>
.dept-aside-container {
  /* 关键点 1：初始宽度设为 15% */
  width: 14vw; /* 或者使用百分比，但在 Grid 容器内使用 vw 更稳定 */
  height: calc(
    100vh - 20px - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height)
  );
  min-width: 200px; /* 防止在极小屏幕下 15% 太窄看不清 */
  box-sizing: border-box;
  flex-shrink: 0;
}

/* 关键点 2：折叠状态 */
.dept-aside-container.is-collapsed {
  width: 0 !important;
  min-width: 0 !important;
  padding: 0 !important;
  margin-right: -16px; /* 抵消父级 grid 的 gap-x-4，让右侧内容贴合 */
  overflow: visible !important;
  pointer-events: none; /* 折叠后不响应鼠标事件，除了 handle */

  /* opacity: 0; */
  box-shadow: none;
}

/* 即使父级折叠，handle 也要可见并可点击 */
.collapse-handle {
  position: absolute;
  top: 50%;
  right: -14px;
  z-index: 200;
  display: flex;
  width: 14px;
  height: 60px;
  color: var(--el-text-color-secondary);
  pointer-events: auto;
  cursor: pointer;
  background-color: var(--el-bg-color);
  border: 1px solid var(--el-border-color-light);
  border-left: none;
  border-radius: 0 12px 12px 0;
  transform: translateY(-50%);
  box-shadow: 2px 0 6px rgb(0 0 0 / 5%);
  transition: right 0.3s;
  align-items: center;
  justify-content: center;
}

.is-collapsed .collapse-handle {
  right: -8px; /* 在边缘露出一半 */
  border-left: 1px solid var(--el-border-color-light);
}

.collapse-handle:hover {
  color: var(--el-color-primary);
  background-color: var(--el-fill-color-light);
}

.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
</style>
