<template>
  <!-- 岗位选择器根容器 -->
  <div class="job-category-selector" ref="selectorRef">

    <!-- 触发按钮：显示已选岗位名称或默认文字"岗位" -->
    <div class="job-category-selector__trigger" :style="{ ...triggerStyle, ...(isHovered || visible ? hoverStyle : {}) }" @click="toggleDropdown" @mouseenter="isHovered = true" @mouseleave="isHovered = false">
      <span class="job-category-selector__display" :style="displayStyle" :title="displayText">{{ displayText }}</span>
      <svg
        class="job-category-selector__arrow"
        :class="{ 'job-category-selector__arrow--open': visible }"
        :style="(isHovered || visible) && hoverStyle?.color ? { color: hoverStyle.color } : {}"
        viewBox="0 0 12 12"
        fill="none"
      >
        <path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
    </div>

    <!-- 下拉面板（Teleport到body，避免被父级overflow:hidden裁切） -->
    <Teleport to="body">
      <div
        v-if="visible"
        class="job-category-selector__panel"
        :class="{
          'job-category-selector__panel--one-col': level === 1,
          'job-category-selector__panel--two-col': level === 2
        }"
        :style="panelStyle"
        @click.stop
      >

      <!-- 选中区：小方块标签展示已选中的岗位名称 -->
      <div class="job-category-selector__selected-area" v-if="selectedItems.length">
        <span
          class="job-category-selector__tag"
          v-for="item in selectedItems"
          :key="item.id"
        >
          {{ item.name }}
          <!-- 点击关闭图标移除该选中项 -->
          <svg class="job-category-selector__tag-close" viewBox="0 0 12 12" @click="removeItem(item)">
            <path d="M3 3L9 9M9 3L3 9" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
          </svg>
        </span>
      </div>

      <!-- 搜索输入框：输入超过 2 个字符时触发模糊匹配 -->
      <div class="job-category-selector__search-wrap">
        <input
          v-model="searchText"
          class="job-category-selector__search"
          placeholder="搜索岗位"
        />
      </div>

      <!-- 搜索结果列表 -->
      <div v-if="searchText.length >= 2 && searchResults.length" class="job-category-selector__search-results">
        <div
          class="job-category-selector__search-item"
          v-for="r in searchResults"
          :key="r.node.id"
          @click="handleSearchItemClick(r.node)"
        >
          <span>{{ r.path }}</span>
          <svg v-if="isSelected(r.node.id)" class="job-category-selector__check" viewBox="0 0 12 12">
            <path d="M2 6L5 9L10 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
          </svg>
        </div>
      </div>

      <!-- 搜索无结果提示 -->
      <div v-else-if="searchText.length >= 2 && !searchResults.length" class="job-category-selector__search-results">
        <div class="job-category-selector__search-empty">无匹配结果</div>
      </div>

      <!-- 提示：双击选中一二级（仅 allowParentSelect 开启且 allowParentSelectClick 关闭时显示） -->
      <div v-if="searchText.length < 2 && allowParentSelect && !allowParentSelectClick" class="job-category-selector__hint">（双击可选中一级/二级岗位分类）</div>

      <!-- 三栏联动选择区（搜索关键词不足 2 字符时显示） -->
      <div v-if="searchText.length < 2" class="job-category-selector__columns">
        <!-- 左栏：一级岗位分类 -->
        <div class="job-category-selector__col job-category-selector__col--left" :class="{ 'job-category-selector__col--full': level === 1 }">
          <div
            class="job-category-selector__col-item"
            :class="{
              'job-category-selector__col-item--active': level > 1 && activeLevel1Id === item.id,
              'job-category-selector__col-item--selected': (level === 1 || allowParentSelect || allowParentSelectClick) && isSelected(item.id)
            }"
            v-for="item in categories"
            :key="item.id"
            @click="selectLevel1(item.id)"
          >
            {{ item.name }}
            <svg v-if="(level === 1 || allowParentSelect || allowParentSelectClick) && isSelected(item.id)" class="job-category-selector__check" viewBox="0 0 12 12">
              <path d="M2 6L5 9L10 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
            </svg>
          </div>
        </div>
        <!-- 中栏：二级岗位分类（level >= 2 时显示） -->
        <div v-if="level >= 2" class="job-category-selector__col job-category-selector__col--mid" :class="{ 'job-category-selector__col--mid-end': level === 2 }">
          <template v-if="level2List.length">
            <div
              class="job-category-selector__col-item"
              :class="{
                'job-category-selector__col-item--active': level > 2 && activeLevel2Id === item.id,
                'job-category-selector__col-item--selected': (level === 2 || allowParentSelect || allowParentSelectClick) && isSelected(item.id)
              }"
              v-for="item in level2List"
              :key="item.id"
              @click="selectLevel2(item.id)"
            >
              {{ item.name }}
              <svg v-if="(level === 2 || allowParentSelect || allowParentSelectClick) && isSelected(item.id)" class="job-category-selector__check" viewBox="0 0 12 12">
                <path d="M2 6L5 9L10 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
              </svg>
            </div>
          </template>
          <div v-else class="job-category-selector__col-empty">请先选择左侧分类</div>
        </div>
        <!-- 右栏：三级岗位（仅 level=3 时显示） -->
        <div v-if="level === 3" class="job-category-selector__col job-category-selector__col--right">
          <template v-if="level3List.length">
            <div
              class="job-category-selector__col-item"
              :class="{ 'job-category-selector__col-item--selected': isSelected(item.id) }"
              v-for="item in level3List"
              :key="item.id"
              @click="selectLevel3(item)"
            >
              {{ item.name }}
              <svg v-if="isSelected(item.id)" class="job-category-selector__check" viewBox="0 0 12 12">
                <path d="M2 6L5 9L10 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
              </svg>
            </div>
          </template>
          <div v-else class="job-category-selector__col-empty">请先选择中间分类</div>
        </div>
      </div>

      <!-- 底部操作按钮 -->
      <div class="job-category-selector__actions">
        <button class="job-category-selector__btn job-category-selector__btn--reset" @click="handleReset">重置</button>
        <button class="job-category-selector__btn job-category-selector__btn--confirm" @click="handleConfirm">确认</button>
      </div>
    </div>
    </Teleport>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue'
import { useStore } from 'vuex'
import type { JobCategoryItem, JobCategoryChild, JobCategoryLeaf } from '@/api/common'

/** 统一的选中节点类型，兼容一二三级 */
type SelectedNode = { id: string; name: string; level: number }

// ==================== 事件与属性定义 ====================

/** 向父组件发送已选岗位 ID 数组（integer[]） */
const emit = defineEmits<{
  (e: 'update:categoryIds', ids: number[]): void
}>()

/** 接收父组件传入的已选岗位 ID 数组 */
const props = withDefaults(
  defineProps<{
    categoryIds?: number[]
    /** 最多可选数量 */
    maxSelect?: number
    /** 是否允许双击选中一二级分类 */
    allowParentSelect?: boolean
    /** 是否允许单击选中父级（选子级时自动移除已选的父级） */
    allowParentSelectClick?: boolean
    /** 展示/选择到第几级：1=只选一级，2=选到二级，3=选到三级 */
    level?: 1 | 2 | 3
    /** 父组件传入的触发按钮自定义样式，用于在不同场景下覆盖默认外观 */
    triggerStyle?: Record<string, string>
    /** 父组件传入的触发按钮 hover 时的自定义样式 */
    hoverStyle?: Record<string, string>
    /** 父组件传入的显示文字自定义样式，用于覆盖 max-width 等默认样式 */
    displayStyle?: Record<string, string>
    /** 自定义触发按钮默认文字，传入后替换"岗位" */
    triggerLabel?: string
  }>(),
  {
    maxSelect: 3,
    allowParentSelect: false,
    allowParentSelectClick: false,
    level: 3,
  }
)

// ==================== 基础引用 ====================

/** Vuex store 实例 */
const store = useStore()

/** 组件根元素引用，用于点击外部关闭判断 */
const selectorRef = ref<HTMLElement | null>(null)

/** 面板的固定定位样式（基于trigger按钮位置动态计算） */
const panelStyle = ref<Record<string, string>>({})

/** 计算面板位置（考虑body transform scale） */
function updatePanelPosition() {
  if (!selectorRef.value) return
  const rect = selectorRef.value.getBoundingClientRect()
  const bodyTransform = document.body.style.transform
  let scale = 1
  const scaleMatch = bodyTransform.match(/scale\(([\d.]+)\)/)
  if (scaleMatch) scale = parseFloat(scaleMatch[1]) || 1
  panelStyle.value = {
    position: 'fixed',
    top: `${(rect.bottom + 6) / scale}px`,
    right: `${(window.innerWidth - rect.right) / scale}px`,
    'z-index': '2000',
  }
}

// ==================== 响应式状态 ====================

/** 下拉面板是否可见 */
const visible = ref(false)

/** 触发按钮是否处于 hover 状态 */
const isHovered = ref(false)

/** 搜索关键词 */
const searchText = ref('')

/** 当前选中的一级分类 ID（左栏高亮项） */
const activeLevel1Id = ref<string>('')

/** 当前选中的二级分类 ID（中栏高亮项） */
const activeLevel2Id = ref<string>('')

/** 已选中的岗位列表（支持一二三级混合选择） */
const selectedItems = ref<SelectedNode[]>([])

/** 一级分类上次点击时间戳，用于双击检测 */
const level1LastClickTime = ref<Record<string, number>>({})

/** 二级分类上次点击时间戳，用于双击检测 */
const level2LastClickTime = ref<Record<string, number>>({})

/** 双击判定间隔（毫秒） */
const DOUBLE_CLICK_DELAY = 500

// ==================== 计算属性 ====================

/** 从全局 store 获取岗位树分类数据 */
const categories = computed<JobCategoryItem[]>(() => store.state.jobCategories)

/** 已选中岗位 ID 集合，用于快速判断某项是否选中 */
const selectedIdSet = computed(() => new Set(selectedItems.value.map(i => i.id)))

/** 触发按钮显示文字：传了triggerLabel就始终显示它，否则无选中显示默认文字，有选中则用逗号拼接名称 */
const displayText = computed(() => {
  if (props.triggerLabel) return props.triggerLabel
  if (!selectedItems.value.length) return '岗位'
  return selectedItems.value.map(i => i.name).join('，')
})

/** 当前一级分类下的二级列表 */
const level2List = computed<JobCategoryChild[]>(() => {
  if (!activeLevel1Id.value) return []
  const parent = categories.value.find(p => p.id === activeLevel1Id.value)
  return parent ? parent.children : []
})

/** 当前二级分类下的三级列表 */
const level3List = computed<JobCategoryLeaf[]>(() => {
  if (!activeLevel2Id.value) return []
  const mid = level2List.value.find(m => m.id === activeLevel2Id.value)
  return mid ? mid.children : []
})

/** 搜索结果：根据 level 和 allowParentSelect/allowParentSelectClick 匹配对应级别 */
const searchResults = computed(() => {
  if (searchText.value.length < 2) return []
  const keyword = searchText.value.toLowerCase()
  const results: { path: string; node: SelectedNode }[] = []
  /** 是否允许选中父级（双击或单击模式均可） */
  const canSelectParent = props.allowParentSelect || props.allowParentSelectClick
  for (const l1 of categories.value) {
    // 一级：level=1 时作为末级可搜索，或允许选中父级且 level>1 时可搜索
    if ((props.level === 1 || canSelectParent) && l1.name.toLowerCase().includes(keyword)) {
      results.push({ path: l1.name, node: { id: l1.id, name: l1.name, level: l1.level } })
    }
    if (props.level >= 2) {
      for (const l2 of l1.children) {
        // 二级：level=2 时作为末级可搜索，或允许选中父级且 level=3 时可搜索
        if ((props.level === 2 || canSelectParent) && l2.name.toLowerCase().includes(keyword)) {
          results.push({ path: `${l1.name} → ${l2.name}`, node: { id: l2.id, name: l2.name, level: l2.level } })
        }
        if (props.level === 3) {
          for (const l3 of l2.children) {
            if (l3.name.toLowerCase().includes(keyword)) {
              results.push({ path: `${l1.name} → ${l2.name} → ${l3.name}`, node: { id: l3.id, name: l3.name, level: l3.level } })
            }
          }
        }
      }
    }
  }
  return results
})

// ==================== 方法 ====================

/** 判断指定岗位 ID 是否已被选中 */
function isSelected(id: string) {
  return selectedIdSet.value.has(id)
}

/** 点击左栏一级分类 */
function selectLevel1(id: string) {
  // level=1 时，一级就是末级，单击直接选中
  if (props.level === 1) {
    const l1 = categories.value.find(c => c.id === id)
    if (l1) toggleItem({ id: l1.id, name: l1.name, level: l1.level })
    return
  }
  // allowParentSelectClick 模式：单击直接选中一级，同时展开子级
  if (props.allowParentSelectClick) {
    const l1 = categories.value.find(c => c.id === id)
    if (l1) toggleItemWithHierarchy({ id: l1.id, name: l1.name, level: l1.level })
    activeLevel1Id.value = id
    activeLevel2Id.value = ''
    return
  }
  if (props.allowParentSelect) {
    const now = Date.now()
    const lastTime = level1LastClickTime.value[id] || 0

    if (now - lastTime < DOUBLE_CLICK_DELAY) {
      const l1 = categories.value.find(c => c.id === id)
      if (l1) toggleItem({ id: l1.id, name: l1.name, level: l1.level })
      level1LastClickTime.value[id] = 0
    } else {
      activeLevel1Id.value = id
      activeLevel2Id.value = ''
      level1LastClickTime.value[id] = now
    }
  } else {
    activeLevel1Id.value = id
    activeLevel2Id.value = ''
  }
}

/** 点击中栏二级分类 */
function selectLevel2(id: string) {
  // level=2 时，二级就是末级，单击直接选中
  if (props.level === 2) {
    const l2 = level2List.value.find(c => c.id === id)
    if (l2) toggleItem({ id: l2.id, name: l2.name, level: l2.level })
    return
  }
  // allowParentSelectClick 模式：单击直接选中二级，同时展开子级
  if (props.allowParentSelectClick) {
    const l2 = level2List.value.find(c => c.id === id)
    if (l2) toggleItemWithHierarchy({ id: l2.id, name: l2.name, level: l2.level })
    activeLevel2Id.value = id
    return
  }
  if (props.allowParentSelect) {
    const now = Date.now()
    const lastTime = level2LastClickTime.value[id] || 0

    if (now - lastTime < DOUBLE_CLICK_DELAY) {
      const l2 = level2List.value.find(c => c.id === id)
      if (l2) toggleItem({ id: l2.id, name: l2.name, level: l2.level })
      level2LastClickTime.value[id] = 0
    } else {
      activeLevel2Id.value = id
      level2LastClickTime.value[id] = now
    }
  } else {
    activeLevel2Id.value = id
  }
}

/** 切换某个岗位节点的选中/取消状态（支持一二三级），超过上限时提示 */
function toggleItem(node: SelectedNode) {
  const idx = selectedItems.value.findIndex(i => i.id === node.id)
  if (idx >= 0) {
    selectedItems.value.splice(idx, 1)
  } else {
    if (selectedItems.value.length >= props.maxSelect) {
      ElMessage.warning(`最多只能选择${props.maxSelect}个岗位`)
      return
    }
    selectedItems.value.push({ ...node })
  }
}

/**
 * allowParentSelectClick 模式下的选中/取消逻辑：
 * - 选中子级时，移除已选中的父级（因为选了更具体的）
 * - 选中父级时，移除已选中的该父级下的所有子级
 */
function toggleItemWithHierarchy(node: SelectedNode) {
  const idx = selectedItems.value.findIndex(i => i.id === node.id)
  if (idx >= 0) {
    // 取消选中
    selectedItems.value.splice(idx, 1)
    return
  }
  // 选中前先做层级互斥处理
  // 获取当前节点的祖先 ID 列表和后代 ID 列表
  const ancestorIds = getAncestorIds(node.id)
  const descendantIds = getDescendantIds(node.id)
  // 移除已选中的祖先和后代
  selectedItems.value = selectedItems.value.filter(
    i => !ancestorIds.has(i.id) && !descendantIds.has(i.id)
  )
  // 检查数量限制
  if (selectedItems.value.length >= props.maxSelect) {
    ElMessage.warning(`最多只能选择${props.maxSelect}个岗位`)
    return
  }
  selectedItems.value.push({ ...node })
}

/** 获取某个节点的所有祖先 ID（向上查找） */
function getAncestorIds(nodeId: string): Set<string> {
  const ancestors = new Set<string>()
  for (const l1 of categories.value) {
    for (const l2 of l1.children) {
      for (const l3 of l2.children) {
        if (l3.id === nodeId) {
          ancestors.add(l2.id)
          ancestors.add(l1.id)
          return ancestors
        }
      }
      if (l2.id === nodeId) {
        ancestors.add(l1.id)
        return ancestors
      }
    }
  }
  return ancestors
}

/** 获取某个节点的所有后代 ID（向下查找） */
function getDescendantIds(nodeId: string): Set<string> {
  const descendants = new Set<string>()
  for (const l1 of categories.value) {
    if (l1.id === nodeId) {
      // 是一级，收集所有二级和三级
      for (const l2 of l1.children) {
        descendants.add(l2.id)
        for (const l3 of l2.children) {
          descendants.add(l3.id)
        }
      }
      return descendants
    }
    for (const l2 of l1.children) {
      if (l2.id === nodeId) {
        // 是二级，收集所有三级
        for (const l3 of l2.children) {
          descendants.add(l3.id)
        }
        return descendants
      }
    }
  }
  return descendants
}

/** 点击右栏三级岗位 */
function selectLevel3(item: { id: string; name: string; level: number }) {
  if (props.allowParentSelectClick) {
    toggleItemWithHierarchy({ id: item.id, name: item.name, level: item.level })
  } else {
    toggleItem({ id: item.id, name: item.name, level: item.level })
  }
}

/** 搜索结果项点击处理 */
function handleSearchItemClick(node: SelectedNode) {
  if (props.allowParentSelectClick) {
    toggleItemWithHierarchy(node)
  } else {
    toggleItem(node)
  }
}

/** 从选中区移除指定岗位 */
function removeItem(item: SelectedNode) {
  selectedItems.value = selectedItems.value.filter(i => i.id !== item.id)
}

/** 重置：清空所有已选项 */
function handleReset() {
  selectedItems.value = []
}

/** 确认：将当前选中结果发送给父组件并关闭面板 */
function handleConfirm() {
  emitIds()
  visible.value = false
}

/** 向父组件发送当前选中的岗位 ID 数组（转为整数） */
function emitIds() {
  emit('update:categoryIds', selectedItems.value.map(i => Number(i.id)))
}

/** 切换下拉面板的显示/隐藏，打开时清空搜索词并默认选中第一个一级分类 */
function toggleDropdown() {
  visible.value = !visible.value
  if (visible.value) {
    searchText.value = ''
    if (categories.value.length && !activeLevel1Id.value) {
      activeLevel1Id.value = categories.value[0].id
    }
    // 计算面板位置
    updatePanelPosition()
  }
}

/** 点击组件外部时关闭下拉面板 */
function onClickOutside(e: MouseEvent) {
  const target = e.target as Node
  if (selectorRef.value && !selectorRef.value.contains(target)) {
    const panel = document.querySelector('.job-category-selector__panel')
    if (panel && panel.contains(target)) return
    visible.value = false
  }
}

// ==================== 生命周期 ====================

onMounted(() => {
  document.addEventListener('click', onClickOutside)
})

onBeforeUnmount(() => {
  document.removeEventListener('click', onClickOutside)
})

// ==================== 监听器 ====================

/** 同步外部传入的 categoryIds 到内部选中状态（支持一二三级） */
function syncFromProps() {
  const ids = props.categoryIds
  if (!ids || !categories.value.length) return
  // 收集所有级别节点到一个 map
  const nodeMap = new Map<string, SelectedNode>()
  for (const l1 of categories.value) {
    nodeMap.set(l1.id, { id: l1.id, name: l1.name, level: l1.level })
    for (const l2 of l1.children) {
      nodeMap.set(l2.id, { id: l2.id, name: l2.name, level: l2.level })
      for (const l3 of l2.children) {
        nodeMap.set(l3.id, { id: l3.id, name: l3.name, level: l3.level })
      }
    }
  }
  selectedItems.value = ids
    .map(id => nodeMap.get(String(id)))
    .filter(Boolean) as SelectedNode[]
}

watch(
  () => props.categoryIds,
  () => syncFromProps(),
  { immediate: true }
)

/** 树数据加载完成后重新同步选中项 */
watch(categories, () => syncFromProps())
</script>
