<template>
  <a-modal :open="visible" :title="title" :width="width" :maskClosable="false" @ok="handleOk" @cancel="handleCancel">
    <!-- 错误提示区域 -->
    <a-alert v-if="errorMessage" :message="errorMessage" :description="errorDetails" type="error" show-icon
      style="margin-bottom: 12px" closable @close="clearError" />

    <!-- 搜索区域 -->
    <div class="search-section">
      <a-form layout="vertical" :model="searchForm">
        <a-form-item label="输入地址">
          <a-input-search v-model:value="searchForm.keyword" placeholder="输入需要查找的地址" enter-button @search="handleSearch"
            :disabled="!mapLoaded || isSearching" allow-clear />
        </a-form-item>
        <a-form-item label="搜索结果" v-if="searchList.length > 0">
          <a-select v-model:value="selectedPlaceId" style="width: 100%" placeholder="请选择搜索结果"
            @change="handlePlaceSelect">
            <a-select-option v-for="item in searchList" :key="item.id" :value="item.id">
              {{ item.name }} - {{ item.address }}
            </a-select-option>
          </a-select>
        </a-form-item>
      </a-form>
    </div>

    <!-- 地图容器，带加载状态 -->
    <div class="map-container" :style="{ height: mapHeight }">
      <div v-if="!mapLoaded" class="map-loading">
        <a-spin size="large" />
        <div class="loading-text">{{ loadingText }}</div>
      </div>

      <!-- 调试信息 (仅开发环境显示) -->
      <!-- <div v-if="debugMode && mapLoaded" class="debug-info">
        <div class="debug-header">调试信息</div>
        <pre>{{ debugInfo }}</pre>
      </div> -->

      <div id="amap-container" class="amap-instance" ref="mapContainer"></div>
    </div>

    <a-form :model="formState" layout="vertical" style="margin-top: 16px">
      <a-form-item label="经纬度">
        <a-input v-model:value="formState.lnglat" readonly placeholder="点击地图或搜索地点选择位置">
          <template #suffix>
            <a-spin v-if="isGeocoding" size="small" />
          </template>
        </a-input>
      </a-form-item>
      <a-form-item label="详细地址">
        <a-input v-model:value="formState.address" readonly placeholder="地址信息将自动显示" />
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, nextTick, reactive, computed } from 'vue'
import { message } from 'ant-design-vue'
import AMapLoader from '@amap/amap-jsapi-loader'
import { debounce } from 'lodash-es'

// 类型定义
interface FormState {
  lnglat: string
  address: string
  location: { lng: number; lat: number } | null
}

interface SearchPlace {
  id: string
  name: string
  address: string
  location: { lng: number; lat: number }
}

interface LocationData {
  lng: number
  lat: number
  address: string
  name?: string
}

// 组件属性
const props = defineProps({
  open: {
    type: Boolean,
    default: false
  },
  title: {
    type: String,
    default: '选择位置'
  },
  width: {
    type: String,
    default: '800px'
  },
  searchPlaceholder: {
    type: String,
    default: '请输入地点名称，如：北京西站、上海外滩'
  },
  defaultCenter: {
    type: Array as () => [number, number],
    default: () => [120.894522, 31.981269] // 南通
  },
  defaultZoom: {
    type: Number,
    default: 12
  },
  searchCity: {
    type: String,
    default: '全国'
  },
  mapHeight: {
    type: String,
    default: '400px'
  },
  debugMode: {
    type: Boolean,
    default: process.env.NODE_ENV === 'development'
  }
})

// 组件事件
const emit = defineEmits(['update:open', 'select', 'error', 'handleGetLng'])

// 状态管理
const visible = ref(false)
const mapLoaded = ref(false)
const isGeocoding = ref(false)
const isSearching = ref(false)
const loadingText = ref('地图加载中...')
const errorMessage = ref('')
const errorDetails = ref('')
const debugInfo = ref('')
const selectedPlaceId = ref('')

const formState: FormState = reactive({
  lnglat: '',
  address: '',
  location: null
})

const searchForm = reactive({
  keyword: ''
})

const searchList = ref<SearchPlace[]>([])

// 地图实例
const mapContainer = ref<HTMLElement>()
let map: AMap.Map | null = null
let marker: AMap.Marker | null = null
let placeSearch: AMap.PlaceSearch | null = null
let geocoder: AMap.Geocoder | null = null
let infoWindow: AMap.InfoWindow | null = null
let markers: AMap.Marker[] = []

// 防抖搜索 (300ms)
const debouncedSearch = debounce((keyword: string) => {
  performSearch(keyword)
}, 300)

// 日志记录
const logDebug = (message: string) => {
  if (props.debugMode) {
    const timestamp = new Date().toLocaleTimeString()
    debugInfo.value = `[${timestamp}] ${message}\n${debugInfo.value}`

    if (debugInfo.value.length > 5000) {
      debugInfo.value = debugInfo.value.substring(0, 5000)
    }
  }
}

// 清除错误信息
const clearError = () => {
  errorMessage.value = ''
  errorDetails.value = ''
  emit('error', null)
}

// 记录错误信息
const setError = (message: string, details?: string) => {
  errorMessage.value = message
  errorDetails.value = details || ''
  emit('error', { message, details })
  logDebug(`错误: ${message} - ${details}`)
}

// 文本转义防XSS
const escapeHtml = (str: string): string => {
  if (!str) return ''
  return str.replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;')
}

// 清理地图资源
const cleanupMap = () => {
  logDebug('开始清理地图资源')
  debouncedSearch.cancel()
  isSearching.value = false

  clearMarkers()

  if (placeSearch) {
    try {
      placeSearch.clear()
      placeSearch.destroy()
      placeSearch = null
      logDebug('搜索服务已销毁')
    } catch (e) {
      logDebug(`清理搜索服务时出错: ${e instanceof Error ? e.message : String(e)}`)
    }
  }

  if (infoWindow) {
    infoWindow.close()
    infoWindow = null
    logDebug('信息窗口已关闭')
  }

  clearMarker()

  if (map) {
    try {
      map.destroy()
      map = null
      logDebug('地图实例已销毁')
    } catch (e) {
      logDebug(`清理地图时出错: ${e instanceof Error ? e.message : String(e)}`)
    }
  }

  mapLoaded.value = false
  isGeocoding.value = false
  clearError()

  Object.assign(formState, {
    lnglat: '',
    address: '',
    location: null
  })
  searchForm.keyword = ''
  searchList.value = []
  selectedPlaceId.value = ''
}

// 清除标记
const clearMarker = () => {
  if (marker) {
    try {
      map?.remove(marker)
      marker = null
      logDebug('主标记已移除')
    } catch (e) {
      logDebug(`清理主标记时出错: ${e instanceof Error ? e.message : String(e)}`)
    }
  }
}

// 清除所有搜索结果标记
const clearMarkers = () => {
  markers.forEach(marker => {
    map?.remove(marker)
  })
  markers = []
  logDebug(`已清除 ${markers.length} 个搜索结果标记`)
}

// 创建标记内容
const createMarkerContent = (name: string, index: number) => {
  const escapedName = escapeHtml(name)
  return `
    <div style="
      background: #1890ff;
      color: white;
      padding: 4px 8px;
      border-radius: 12px;
      font-size: 12px;
      white-space: nowrap;
      border: 2px solid white;
      box-shadow: 0 2px 6px rgba(0,0,0,0.3);
    ">
      ${index}. ${escapedName}
    </div>
  `
}

// 显示位置信息窗口
const showLocationInfo = (place: SearchPlace, isSearchResult: boolean = false) => {
  if (infoWindow) {
    infoWindow.close()
  }

  const escapedName = escapeHtml(place.name)
  const escapedAddress = escapeHtml(place.address || '地址不详')

  const content = `
    <div style="padding: 8px; max-width: 200px;">
      <div style="font-weight: bold; margin-bottom: 4px;">${escapedName}</div>
      <div style="color: #666; font-size: 12px;">${escapedAddress}</div>
      <div style="color: #999; font-size: 12px; margin-top: 4px;">
        ${isSearchResult ? '搜索结果' : '选中位置'}
      </div>
    </div>
  `

  infoWindow = new AMap.InfoWindow({
    content: content,
    offset: new AMap.Pixel(0, -30),
    position: [place.location.lng, place.location.lat]
  })

  infoWindow.open(map, [place.location.lng, place.location.lat])
  logDebug(`显示位置信息: ${place.name}`)
}

// 处理搜索结果
const handleSearchComplete = (result: AMap.PlaceSearchResult) => {
  isSearching.value = false
  logDebug(`搜索完成: ${result.info}, 结果数: ${result.poiList?.pois?.length || 0}`)

  if (result.info === 'OK' && result.poiList?.pois?.length > 0) {
    const pois = result.poiList.pois

    // 更新搜索结果列表
    searchList.value = pois.map((poi: any) => ({
      id: poi.id,
      name: poi.name,
      address: poi.address,
      location: {
        lng: poi.location.lng,
        lat: poi.location.lat
      }
    }))

    // 清除之前的标记
    clearMarkers()

    // 为每个结果添加标记
    pois.forEach((poi: any, index: number) => {
      const position = [poi.location.lng, poi.location.lat]
      const poiMarker = new AMap.Marker({
        position: position,
        map: map,
        title: poi.name,
        content: createMarkerContent(poi.name, index + 1),
        offset: new AMap.Pixel(-15, -42)
      })

      // 点击标记事件
      poiMarker.on('click', () => {
        const place: SearchPlace = {
          id: poi.id,
          name: poi.name,
          address: poi.address,
          location: { lng: poi.location.lng, lat: poi.location.lat }
        }
        updateSelectedLocation([poi.location.lng, poi.location.lat], place)
        showLocationInfo(place, true)
        selectedPlaceId.value = poi.id
      })

      markers.push(poiMarker)
    })

    // 自动选中第一个结果
    if (pois.length > 0) {
      setTimeout(() => {
        const firstPoi = pois[0]
        const place: SearchPlace = {
          id: firstPoi.id,
          name: firstPoi.name,
          address: firstPoi.address,
          location: { lng: firstPoi.location.lng, lat: firstPoi.location.lat }
        }
        selectedPlaceId.value = firstPoi.id
        updateSelectedLocation([firstPoi.location.lng, firstPoi.location.lat], place)
        map?.setCenter([firstPoi.location.lng, firstPoi.location.lat])
        map?.setZoom(16)
      }, 100)
    }

    map?.setFitView()
  } else {
    message.info('未找到相关地点')
    searchList.value = []
    logDebug('未找到相关地点')
  }
}

// 执行实际搜索
const performSearch = (keyword: string) => {
  if (!placeSearch) {
    setError('搜索服务未初始化', '请等待地图加载完成后再试')
    return
  }

  if (!mapLoaded.value) {
    setError('地图未加载完成', '请等待地图加载完成后再试')
    return
  }

  isSearching.value = true
  searchList.value = []
  selectedPlaceId.value = ''
  logDebug(`执行搜索: ${keyword}`)

  try {
    placeSearch.clear()
    clearMarkers()
    placeSearch.search(keyword)
  } catch (e) {
    isSearching.value = false
    const errorMsg = e instanceof Error ? e.message : '搜索执行失败'
    setError('搜索执行失败', errorMsg)
    message.error('搜索过程中发生错误')
  }
}

// 创建搜索服务
const createPlaceSearch = () => {
  if (!map) return

  logDebug(`创建PlaceSearch实例，城市限制: ${props.searchCity}`)

  try {
    placeSearch = new AMap.PlaceSearch({
      map: map,
      pageSize: 10,
      city: props.searchCity,
      citylimit: props.searchCity !== '全国',
      autoFitView: true
    })

    placeSearch.on('complete', handleSearchComplete)
    placeSearch.on('error', (error: any) => {
      isSearching.value = false
      logDebug(`搜索错误: 代码=${error.errorCode}, 信息=${error.errorMsg}, 状态=${error.status}`)

      let userMsg = '搜索服务出错，请重试'
      let details = `错误代码: ${error.errorCode}, 信息: ${error.errorMsg}`

      switch (error.errorCode) {
        case 10001:
          userMsg = 'API Key错误或已过期'
          details += '\n解决方案: 检查并更新高德地图API Key'
          break
        case 10002:
          userMsg = '没有使用该服务的权限'
          details += '\n解决方案: 在高德开放平台为当前Key开启POI搜索权限'
          break
        case 10003:
          userMsg = '请求来源未被授权'
          details += '\n解决方案: 将当前域名添加到Key的Referer白名单中'
          break
        case 10004:
          userMsg = '服务调用配额不足'
          details += '\n解决方案: 检查服务调用配额或升级服务'
          break
        case 10005:
          userMsg = '服务暂不可用'
          details += '\n解决方案: 稍后重试或联系高德技术支持'
          break
      }

      setError(userMsg, details)
      message.error(userMsg)
    })
  } catch (e) {
    const errorMsg = e instanceof Error ? e.message : '创建搜索服务失败'
    setError('搜索服务初始化失败', errorMsg)
    logDebug(`创建搜索服务失败: ${errorMsg}`)
  }
}

// 创建地理编码服务
const createGeocoder = () => {
  try {
    geocoder = new AMap.Geocoder({
      radius: 1000,
      extensions: 'all',
      city: '全国'
    })
    logDebug('地理编码服务已创建')
  } catch (e) {
    const errorMsg = e instanceof Error ? e.message : '创建地理编码服务失败'
    setError('地理编码服务初始化失败', errorMsg)
    logDebug(`创建地理编码服务失败: ${errorMsg}`)
  }
}

// 初始化地图插件
const initPlugins = async (): Promise<void> => {
  logDebug('初始化地图插件')

  return new Promise((resolve, reject) => {
    AMap.plugin(['AMap.PlaceSearch', 'AMap.Geocoder', 'AMap.ToolBar', 'AMap.Scale'], () => {
      logDebug('插件加载回调触发')

      try {
        createPlaceSearch()
        createGeocoder()

        // 添加控件
        map?.addControl(new AMap.ToolBar())
        map?.addControl(new AMap.Scale())

        logDebug('插件加载成功')
        resolve()
      } catch (e) {
        const errorMsg = e instanceof Error ? e.message : '插件初始化失败'
        logDebug(`插件初始化失败: ${errorMsg}`)
        reject(new Error(errorMsg))
      }
    })
  })
}

// 更新选中位置信息
const updateSelectedLocation = async (position: [number, number], place?: SearchPlace) => {
  const [lng, lat] = position
  formState.lnglat = `${lng.toFixed(6)}, ${lat.toFixed(6)}`
  formState.location = { lng, lat }
  logDebug(`位置更新: ${formState.lnglat}`)

  // 更新标记
  updateMarker(position)

  // 地址反查
  if (geocoder) {
    isGeocoding.value = true
    geocoder.getAddress(position, (status, result) => {
      isGeocoding.value = false

      if (status === 'complete' && result.regeocode) {
        formState.address = result.regeocode.formattedAddress
        logDebug(`地址反查成功: ${formState.address}`)

        // 触发 handleGetLng 事件
        const locationData: LocationData = {
          lng,
          lat,
          address: formState.address,
          name: place?.name
        }
        emit('handleGetLng', locationData)
      } else if (place?.address) {
        formState.address = place.address
        logDebug(`使用POI地址: ${formState.address}`)

        const locationData: LocationData = {
          lng,
          lat,
          address: place.address,
          name: place.name
        }
        emit('handleGetLng', locationData)
      } else {
        formState.address = '地址不详'
        logDebug('地址反查失败')

        const locationData: LocationData = {
          lng,
          lat,
          address: '地址不详'
        }
        emit('handleGetLng', locationData)
      }
    })
  } else if (place?.address) {
    formState.address = place.address
    logDebug(`使用POI地址: ${formState.address}`)

    const locationData: LocationData = {
      lng,
      lat,
      address: place.address,
      name: place.name
    }
    emit('handleGetLng', locationData)
  }
}

// 更新标记位置
const updateMarker = (position: [number, number]) => {
  if (!map) return

  clearMarker()

  try {
    marker = new AMap.Marker({
      position: position,
      map: map,
      draggable: true,
      icon: new AMap.Icon({
        size: new AMap.Size(36, 36),
        image: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
        imageSize: new AMap.Size(36, 36)
      })
    })

    marker.on('dragend', (event) => {
      const newPosition = [event.lnglat.lng, event.lnglat.lat] as [number, number]
      updateSelectedLocation(newPosition)
    })

    logDebug(`标记已更新到: ${position.join(', ')}`)
  } catch (e) {
    const errorMsg = e instanceof Error ? e.message : '创建标记失败'
    logDebug(`更新标记失败: ${errorMsg}`)
    message.error('更新位置标记失败')
  }
}

// 处理地图点击事件
const handleMapClick = (e: any) => {
  const lng = e.lnglat.getLng()
  const lat = e.lnglat.getLat()

  // 清除搜索结果
  clearMarkers()
  searchList.value = []
  selectedPlaceId.value = ''

  updateSelectedLocation([lng, lat])

  // 使用逆地理编码获取地址信息
  if (geocoder) {
    geocoder.getAddress([lng, lat], (status, result) => {
      if (status === 'complete' && result.regeocode) {
        const address = result.regeocode.formattedAddress

        // 添加信息窗口
        if (infoWindow) {
          infoWindow.close()
        }

        infoWindow = new AMap.InfoWindow({
          content: `
            <div style="padding:10px;min-width:200px;">
              <div style="font-weight:bold;margin-bottom:5px;">点击位置</div>
              <div>${address}</div>
              <div style="margin-top:8px;color:#666;">
                <div>经度: ${lng.toFixed(6)}</div>
                <div>纬度: ${lat.toFixed(6)}</div>
              </div>
            </div>
          `,
          offset: new AMap.Pixel(0, -35)
        })

        infoWindow.open(map, [lng, lat])
      }
    })
  }
}

// 初始化地图
const initMap = async () => {
  logDebug('开始初始化地图')
  clearError()

  if (!mapContainer.value) {
    const errorMsg = '地图容器元素未找到'
    setError('初始化失败', errorMsg)
    console.error(errorMsg)
    return
  }

  try {
    loadingText.value = '正在初始化地图...'

    // 安全密钥配置
    window._AMapSecurityConfig = {
      securityJsCode: 'df197447a4adc77f0cb376a44462272c'
    }

    // 加载地图 SDK
    const AMap = await AMapLoader.load({
      key: "38b334d84b1f89aa39d4efae76f0b341",
      version: "2.0",
      plugins: ['AMap.ToolBar', 'AMap.Scale', 'AMap.Geocoder', 'AMap.PlaceSearch']
    })

    // 初始化地图
    map = new AMap.Map('amap-container', {
      zoom: props.defaultZoom,
      center: props.defaultCenter,
      viewMode: "3D",
      resizeEnable: true
    })

    map.on('complete', () => {
      logDebug('地图加载完成')
      mapLoaded.value = true
      loadingText.value = '地图加载中...'

      initPlugins().catch(error => {
        console.error('插件初始化失败:', error)
        setError('功能初始化失败', error.message)
        message.error('地图功能初始化失败: ' + error.message)
      })
    })

    map.on('click', handleMapClick)

    // 监听地图错误
    map.on('error', (error) => {
      const errorMsg = error.error || '地图加载错误'
      logDebug(`地图错误: ${errorMsg}`)
      setError('地图加载错误', errorMsg)
    })

  } catch (error) {
    const errorMsg = error instanceof Error ? error.message : '地图初始化失败'
    logDebug(`地图初始化失败: ${errorMsg}`)
    setError('地图初始化失败', errorMsg)
    message.error('地图初始化失败，请重试')
  }
}

// 处理搜索
const handleSearch = (keyword: string) => {
  clearError()

  if (!keyword?.trim()) {
    message.warning('请输入搜索关键词')
    debouncedSearch.cancel()
    searchList.value = []
    selectedPlaceId.value = ''
    clearMarkers()
    return
  }

  if (!placeSearch) {
    message.warning('搜索服务初始化中，请稍后重试')
    logDebug('搜索服务尚未初始化，等待初始化后重试')

    initPlugins().then(() => {
      handleSearch(keyword)
    }).catch(() => {
      message.error('搜索功能初始化失败，无法执行搜索')
    })
    return
  }

  if (!mapLoaded.value) {
    message.warning('地图尚未加载完成，请稍后重试')
    return
  }

  debouncedSearch(keyword.trim())
}

// 处理地点选择
const handlePlaceSelect = (placeId: string) => {
  const selectedPlace = searchList.value.find(item => item.id === placeId)
  if (selectedPlace) {
    updateSelectedLocation([selectedPlace.location.lng, selectedPlace.location.lat], selectedPlace)
    map?.setCenter([selectedPlace.location.lng, selectedPlace.location.lat])
    map?.setZoom(16)
    showLocationInfo(selectedPlace, true)
  }
}

// 确认选择
const handleOk = () => {
  if (!formState.location) {
    message.warning('请先在地图上选择一个位置')
    return
  }

  emit('select', {
    lnglat: formState.lnglat,
    address: formState.address,
    location: formState.location
  })

  handleCancel()
}

// 取消选择
const handleCancel = () => {
  visible.value = false
  emit('update:open', false)
  cleanupMap()
}

// 同步弹框状态
watch(
  () => props.open,
  (val) => {
    logDebug(`弹窗状态变化: ${val}`)
    visible.value = val
    if (val) {
      nextTick(() => {
        initMap()
      })
    } else {
      cleanupMap()
    }
  },
  { immediate: true }
)

watch(visible, (val) => {
  if (!val) {
    emit('update:open', false)
  }
})

// 组件卸载时清理
onUnmounted(() => {
  logDebug('组件卸载，清理资源')
  cleanupMap()
})
</script>

<style scoped>
:deep(.ant-input-search) {
  width: 100%;
}

.search-section {
  margin-bottom: 16px;
}

.map-container {
  position: relative;
  width: 100%;
  border: 1px solid #d9d9d9;
  border-radius: 6px;
  overflow: hidden;
}

.amap-instance {
  width: 100%;
  height: 100%;
}

.map-loading {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.8);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 10;
}

.loading-text {
  margin-top: 16px;
  color: #666;
  font-size: 14px;
}

.debug-info {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  font-size: 12px;
  padding: 8px;
  max-height: 150px;
  overflow-y: auto;
  z-index: 100;
}

.debug-header {
  font-weight: bold;
  margin-bottom: 4px;
  padding-bottom: 4px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}

:deep(.ant-alert) {
  margin-bottom: 12px;
}
</style>