<template>
  <!-- 地区选择器根容器 -->
  <div class="region-selector" ref="selectorRef">

    <!-- 触发按钮：显示已选地区名称或默认文字"城市" -->
    <div class="region-selector__trigger" :style="{ ...triggerStyle, ...(isHovered || visible ? hoverStyle : {}) }" @click="toggleDropdown" @mouseenter="isHovered = true" @mouseleave="isHovered = false">
      <span class="region-selector__display" :style="displayStyle" :title="displayText">{{ displayText }}</span>
      <svg
        class="region-selector__arrow"
        :class="{ 'region-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="region-selector__panel"
        :class="{ 'region-selector__panel--two-col': level === 2 }"
        :style="panelStyle"
        @click.stop
      >

      <!-- 选中区：小方块标签展示已选中的地区名称 -->
      <div class="region-selector__selected-area" v-if="selectedItems.length">
        <span
          class="region-selector__tag"
          v-for="item in selectedItems"
          :key="item.code"
        >
          {{ item.name }}
          <svg class="region-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>

      <!-- 搜索输入框 -->
      <div class="region-selector__search-wrap">
        <input
          v-model="searchText"
          class="region-selector__search"
          placeholder="搜索地区"
        />
      </div>

      <!-- 搜索结果列表 -->
      <div v-if="searchText.length >= 2 && searchResults.length" class="region-selector__search-results">
        <div
          class="region-selector__search-item"
          v-for="r in searchResults"
          :key="r.item.code"
          @click="toggleItem(r.item)"
        >
          <span>{{ r.path }}</span>
          <svg v-if="isSelected(r.item.code)" class="region-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="region-selector__search-results">
        <div class="region-selector__search-empty">无匹配结果</div>
      </div>

      <!-- 分栏联动选择区（搜索关键词不足 2 字符时显示） -->
      <div v-if="searchText.length < 2" class="region-selector__columns">
        <!-- 左栏：省级列表 -->
        <div class="region-selector__col region-selector__col--left">
          <div
            class="region-selector__col-item"
            :class="{ 'region-selector__col-item--active': activeProvinceCode === item.code }"
            v-for="item in regions"
            :key="item.code"
            @click="selectProvince(item.code)"
          >
            {{ item.name }}
          </div>
        </div>
        <!-- 中栏：市级列表（level=2 时为末级可选中，level=3 时为中间栏） -->
        <div class="region-selector__col region-selector__col--mid">
          <template v-if="cityList.length">
            <div
              class="region-selector__col-item"
              :class="cityItemClass(item)"
              v-for="item in cityList"
              :key="item.code"
              @click="onCityClick(item)"
            >
              {{ item.name }}
              <!-- level=2 时显示选中勾 -->
              <svg v-if="level === 2 && isSelected(item.code)" class="region-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="region-selector__col-empty">请先选择左侧省份</div>
        </div>
        <!-- 右栏：区县级列表（仅 level=3 时显示） -->
        <div v-if="level === 3" class="region-selector__col region-selector__col--right">
          <template v-if="districtList.length">
            <div
              class="region-selector__col-item"
              :class="{ 'region-selector__col-item--selected': isSelected(item.code) }"
              v-for="item in districtList"
              :key="item.code"
              @click="toggleItem(item)"
            >
              {{ item.name }}
              <svg v-if="isSelected(item.code)" class="region-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="region-selector__col-empty">请先选择中间城市</div>
        </div>
      </div>

      <!-- 底部操作按钮 -->
      <div class="region-selector__actions">
        <button class="region-selector__btn region-selector__btn--reset" @click="handleReset">重置</button>
        <button class="region-selector__btn region-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 { RegionItem, RegionChild, RegionLeaf } from '@/api/common'

// ==================== 选中项的统一类型（code + name） ====================

/** 选中项统一结构 */
interface SelectedRegion {
  code: string
  name: string
}

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

/** 向父组件发送已选地区编码数组（string[]） */
const emit = defineEmits<{
  (e: 'update:regionCodes', codes: string[]): void
}>()

/** 接收父组件传入的属性 */
const props = withDefaults(
  defineProps<{
    /** 已选地区编码数组 */
    regionCodes?: string[]
    /** 选择级别：2=选到市级，3=选到区县级 */
    level?: 2 | 3
    /** 最多可选数量 */
    maxSelect?: number
    /** 父组件传入的触发按钮自定义样式，用于在不同场景下覆盖默认外观 */
    triggerStyle?: Record<string, string>
    /** 父组件传入的触发按钮 hover 时的自定义样式 */
    hoverStyle?: Record<string, string>
    /** 父组件传入的显示文字自定义样式，用于覆盖 max-width 等默认样式 */
    displayStyle?: Record<string, string>
    /** 自定义触发按钮默认文字，传入后替换"城市" */
    triggerLabel?: string
  }>(),
  {
    level: 2,
    maxSelect: 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('')

/** 当前选中的省级编码（左栏高亮项） */
const activeProvinceCode = ref<string>('')

/** 当前选中的市级编码（中栏高亮项，仅 level=3 时使用） */
const activeCityCode = ref<string>('')

/** 已选中的地区列表 */
const selectedItems = ref<SelectedRegion[]>([])

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

/** 从全局 store 获取地区树分类数据 */
const regions = computed<RegionItem[]>(() => store.state.regions)

/** 已选中编码集合，用于快速判断 */
const selectedCodeSet = computed(() => new Set(selectedItems.value.map(i => i.code)))

/** 触发按钮显示文字 */
const displayText = computed(() => {
  if (props.triggerLabel) return props.triggerLabel
  if (!selectedItems.value.length) return '城市'
  return selectedItems.value.map(i => i.name).join('，')
})

/** 当前省级下的市级列表 */
const cityList = computed<RegionChild[]>(() => {
  if (!activeProvinceCode.value) return []
  const province = regions.value.find(p => p.code === activeProvinceCode.value)
  return province ? province.children : []
})

/** 当前市级下的区县级列表（仅 level=3 时有意义） */
const districtList = computed<RegionLeaf[]>(() => {
  if (!activeCityCode.value) return []
  const city = cityList.value.find(c => c.code === activeCityCode.value)
  return city?.children || []
})

/** 搜索结果：模糊匹配目标级别的 name，返回带路径的结果 */
const searchResults = computed(() => {
  if (searchText.value.length < 2) return []
  const keyword = searchText.value.toLowerCase()
  const results: { path: string; item: SelectedRegion }[] = []

  for (const province of regions.value) {
    if (props.level === 2) {
      // 选到市级：匹配市级 name
      for (const city of province.children) {
        if (city.name.toLowerCase().includes(keyword)) {
          results.push({
            path: `${province.name} → ${city.name}`,
            item: { code: city.code, name: city.name },
          })
        }
      }
    } else {
      // 选到区县级：匹配区县级 name
      for (const city of province.children) {
        if (city.children) {
          for (const district of city.children) {
            if (district.name.toLowerCase().includes(keyword)) {
              results.push({
                path: `${province.name} → ${city.name} → ${district.name}`,
                item: { code: district.code, name: district.name },
              })
            }
          }
        }
      }
    }
  }
  return results
})

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

/** 判断指定编码是否已被选中 */
function isSelected(code: string) {
  return selectedCodeSet.value.has(code)
}

/** 点击左栏省级，切换中栏并清空右栏 */
function selectProvince(code: string) {
  activeProvinceCode.value = code
  activeCityCode.value = ''
}

/** 点击中栏市级：level=2 时直接选中/取消，level=3 时切换右栏 */
function onCityClick(city: RegionChild) {
  if (props.level === 2) {
    toggleItem({ code: city.code, name: city.name })
  } else {
    activeCityCode.value = city.code
  }
}

/** 中栏行的 class：level=2 时用 selected 样式，level=3 时用 active 样式 */
function cityItemClass(city: RegionChild) {
  if (props.level === 2) {
    return { 'region-selector__col-item--selected': isSelected(city.code) }
  }
  return { 'region-selector__col-item--active': activeCityCode.value === city.code }
}

/** 切换某个地区的选中/取消状态 */
function toggleItem(item: SelectedRegion) {
  const idx = selectedItems.value.findIndex(i => i.code === item.code)
  if (idx >= 0) {
    selectedItems.value.splice(idx, 1)
  } else {
    if (selectedItems.value.length >= props.maxSelect) {
      ElMessage.warning(`最多只能选择${props.maxSelect}个地区`)
      return
    }
    selectedItems.value.push({ ...item })
  }
}

/** 从选中区移除指定地区 */
function removeItem(item: SelectedRegion) {
  selectedItems.value = selectedItems.value.filter(i => i.code !== item.code)
}

/** 重置：清空所有已选项并关闭面板 */
function handleReset() {
  selectedItems.value = []
  emitCodes()
  setTimeout(() => {
    visible.value = false
  }, 0)
}

/** 确认：将当前选中结果发送给父组件并关闭面板 */
function handleConfirm() {
  emitCodes()
  // 延迟关闭面板，避免 v-if 移除面板后同一个 click 事件落到 trigger 上触发 toggleDropdown
  setTimeout(() => {
    visible.value = false
  }, 0)
}

/** 向父组件发送当前选中的地区编码数组 */
function emitCodes() {
  emit('update:regionCodes', selectedItems.value.map(i => i.code))
}

/** 切换下拉面板的显示/隐藏 */
function toggleDropdown() {
  visible.value = !visible.value
  if (visible.value) {
    searchText.value = ''
    // 如果 store 中地区数据为空（页面刷新等场景），主动请求加载
    if (!regions.value.length) {
      store.dispatch('loadCommonData')
    }
    if (regions.value.length && !activeProvinceCode.value) {
      activeProvinceCode.value = regions.value[0].code
    }
    // 计算面板位置
    updatePanelPosition()
  }
}

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

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

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

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

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

/** 同步外部传入的 regionCodes 到内部选中状态 */
function syncFromProps() {
  const codes = props.regionCodes
  if (!codes || !regions.value.length) return
  // 根据 level 收集对应级别的所有节点
  const allNodes: SelectedRegion[] = []
  for (const province of regions.value) {
    if (props.level === 2) {
      for (const city of province.children) {
        allNodes.push({ code: city.code, name: city.name })
      }
    } else {
      for (const city of province.children) {
        if (city.children) {
          for (const district of city.children) {
            allNodes.push({ code: district.code, name: district.name })
          }
        }
      }
    }
  }
  selectedItems.value = codes
    .map(code => allNodes.find(n => n.code === code))
    .filter(Boolean) as SelectedRegion[]
}

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

/** 树数据加载完成后重新同步选中项（解决并行加载时树数据晚于 prop 到达的问题） */
watch(regions, () => {
  syncFromProps()
  // 地区数据加载完成后，如果面板已打开且没有激活省份，默认选中第一个
  if (visible.value && regions.value.length && !activeProvinceCode.value) {
    activeProvinceCode.value = regions.value[0].code
  }
})
</script>
