<template>
  <div class="edit-page">
    <!-- 地图容器 -->
    <div class="map-container">
      <!-- 左侧工具栏 -->
      <div class="toolbar-container">
        <MapToolbar
          preset="edit"
          :selected-key="currentMode"
          @mode-change="handleModeChange"
          @zoom-in="handleZoomIn"
          @zoom-out="handleZoomOut"
          @center-robot="handleCenterRobot"
          @toggle-fullscreen="handleToggleFullscreen"
          @save="handleSaveMap"
        />
      </div>

      <!-- 地图组件（作为主内容区域） -->
      <div id="map-stage" class="page-content" ref="mapContentRef">
        <OlMap
          ref="olmapRef"
          :width="olWidth + 'px'"
          :height="olHeight + 'px'"
          backgroundColor="#F5F5F5"
          :mapName="mapName"
          :robotPoseData="robotPoseData"
          :pointDraSelectEnabled="pointDraSelectEnabled"
          :showDefaultControls="false"
          @elementRoadInitEnd="elementRoadInitEnd"
          @elementRoadDrawEnd="elementRoadDrawEnd"
          @removeElementResult="removeElementResult"
          @selectShowEleResult="selectShowEleResult"
        />

        <!-- 底部Inspector面板 -->
        <BottomInspector
          ref="bottomInspectorRef"
          :visible="inspector.visible"
          :mode="inspector.mode"
          :data="inspector.data"
          :loading="inspector.loading"
          @edit="handleInspectorEdit"
          @save="handleInspectorSave"
          @cancel="handleInspectorCancel"
          @close="handleInspectorClose"
          @locate="handleInspectorLocate"
          @height-change="handleInspectorHeightChange"
        />
      </div>

      <!-- 右侧面板 -->
      <div class="panel-container">
        <RightPanel
          mode="edit"
          panelType="edit"
          :overlay="true"
          :tabs="rightPanelTabs"
          :initial-tab="'info'"
          :realtime-info="realtimeInfo"
          :element-list="allElementList"
          :selected-element="currentFeature"
          :element-types="elementTypeCounts"
          @add-current-point="handleAddCurrentPoint"
          @element-select="handleElementSelect"
          @element-edit="handleElementEdit"
          @element-locate="handleElementLocate"
          @element-remove="handleElementRemove"
          @network-export="handleNetworkExport"
          @network-import="handleNetworkImport"
        />
      </div>
    </div>

    <!-- 添加当前点对话框 -->
    <el-dialog
      v-model="addCurrentMapShow"
      title="添加当前实时位姿点"
      width="480px"
      @open="openCurrentToMapDialog"
      class="add-pose-dialog"
      :close-on-click-modal="false"
      center
      destroy-on-close
    >
      <div class="dialog-content">
        <el-form ref="currentPointFormRef" :model="currentRobotRecord" label-width="90px" size="small" class="pose-form">
          <div class="form-section">
            <h4 class="section-title">
              <el-icon><Location /></el-icon>
              位置信息
            </h4>
            <el-form-item label="X坐标(m)" prop="x">
              <el-input-number
                v-model="currentRobotRecord.x"
                :precision="3"
                :step="0.1"
                controls-position="right"
                placeholder="请输入X坐标值"
                class="coordinate-input"
                style="width: 100%;"
              />
            </el-form-item>
            <el-form-item label="Y坐标(m)" prop="y">
              <el-input-number
                v-model="currentRobotRecord.y"
                :precision="3"
                :step="0.1"
                controls-position="right"
                placeholder="请输入Y坐标值"
                class="coordinate-input"
                style="width: 100%;"
              />
            </el-form-item>
            <el-form-item label="Z坐标(m)" prop="z">
              <el-input-number
                v-model="currentRobotRecord.z"
                :precision="3"
                :step="0.1"
                controls-position="right"
                placeholder="请输入Z坐标值"
                class="coordinate-input"
                style="width: 100%;"
              />
            </el-form-item>
          </div>

          <div class="form-section">
            <h4 class="section-title">
              <el-icon><Guide /></el-icon>
              方向配置
            </h4>
            <el-form-item label="航偏角(rad)" prop="angle">
              <el-input-number
                v-model="currentRobotRecord.angle"
                :precision="3"
                :step="0.1"
                controls-position="right"
                placeholder="请输入航偏角值"
                style="width: 100%;"
              />
            </el-form-item>
            <el-form-item label="航偏角使能" prop="angleEnable">
              <el-switch v-model="currentRobotRecord.angleEnable" />
            </el-form-item>
          </div>
        </el-form>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="addCurrentMapShow = false">取 消</el-button>
          <el-button type="primary" @click="addCurrentToMap">
            <el-icon><Check /></el-icon> 确 定
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
import { Location, Guide, Check } from '@element-plus/icons-vue'
import OlMap from "@/components/OlMap"
import MapToolbar from "../components/shared/MapToolbar.vue"
import RightPanel from "../components/shared/RightPanel.vue"
import BottomInspector from "@/components/BottomInspector.vue"
import { saveRoadMapGeoJson } from "@/api/robot/map"
import { initWebSocket, disconnect } from "@/utils/websocket"

defineOptions({
  name: 'EditPage'
})

// === Route & Router ===
const route = useRoute()
const router = useRouter()

// === Template Refs ===
const mapContentRef = ref(null)
const olmapRef = ref(null)
const bottomInspectorRef = ref(null)
const currentPointFormRef = ref(null)

// === Reactive State ===
const mapName = ref(route.params.mapName || '')

const olWidth = ref(0)
const olHeight = ref(0)

const currentMode = ref('select-mode')
const pointDraSelectEnabled = ref(true)

const inspector = reactive({
  visible: false,
  mode: 'view',
  data: null,
  loading: false
})

const rightPanelTabs = ref(['info', 'elements', 'network'])

const realtimeInfo = reactive({
  currentMap: route.params.mapName || 'Unknown',
  currentTask: '地图编辑',
  speed: '0m/s',
  speedCommand: '0m/s',
  coordinates: '(0, 0, 0)',
  heading: '0°',
  totalDistance: '0m',
  registrationError: '0',
  batteryLevel: '0%'
})

const pointData = ref([])
const lineData = ref([])
const bowData = ref([])
const shapeData = ref([])
const currentFeature = ref({})

const addCurrentMapShow = ref(false)
const currentRobotRecord = reactive({
  x: 0,
  y: 0,
  z: 0,
  angle: 0,
  angleEnable: false
})

const robotPoseData = reactive({
  x: 0,
  y: 0,
  angle: 0
})

const haveDraw = ref(false)
const wsDeviceId = ref('ld000001')

// === Computed ===
const allElementList = computed(() => {
  return [
    ...pointData.value,
    ...lineData.value,
    ...bowData.value,
    ...shapeData.value
  ]
})

const elementTypeCounts = computed(() => [
  { key: 'point', label: '点', count: pointData.value.length },
  { key: 'line', label: '线', count: lineData.value.length },
  { key: 'curve', label: '弧', count: bowData.value.length },
  { key: 'polygon', label: '面', count: shapeData.value.length }
])

// === Methods ===
const updateMapSize = () => {
  const mapContent = mapContentRef.value
  if (mapContent) {
    olWidth.value = mapContent.offsetWidth
    olHeight.value = mapContent.offsetHeight
  }
}

const updateRightWidth = (width) => {
  const host = mapContentRef.value?.ownerDocument?.documentElement || document.documentElement
  host.style.setProperty('--right-panel-width', `${width}px`)
}

const initEditMode = () => {
  currentMode.value = 'select-mode'
  pointDraSelectEnabled.value = true
  console.log('编辑模式初始化完成，当前模式:', currentMode.value)
}

const handleBeforeUnload = (event) => {
  if (haveDraw.value) {
    event.preventDefault()
    event.returnValue = ""
  }
}

// === WebSocket ===
const setupWebSocket = () => {
  initWebSocket({
    // deviceId 使用 websocket.js 中的默认值 'ld000001'
    onConnect: () => {
      console.log('WebSocket连接成功')
    },
    onDisconnect: () => {
      console.log('WebSocket连接断开')
    },
    onMessage: (type, message) => {
      handleWsMessage(type, message)
    },
    onError: (error) => {
      console.error('WebSocket错误:', error)
    }
  })
}

const handleWsMessage = (type, message) => {
  console.log("znm",type);
  
  switch (type) {
    case 'pose':
      handlePoseMessage(message)
      break
    case 'raw':
      if (message.topic && message.topic.includes('battery')) {
        handleBatteryMessage(message)
      }
      break
  }
}

const handlePoseMessage = (data) => {
  console.log("data:",data);
  
  try {
    const pose = data.data || data
    const { xyz, rpy } = pose

    if (xyz) {
      robotPoseData.x = xyz[0]
      robotPoseData.y = xyz[1]
      robotPoseData.angle = rpy ? rpy[2] : 0
      currentRobotRecord.x = xyz[0]
      currentRobotRecord.y = xyz[1]
      currentRobotRecord.z = xyz[2] || 0
      currentRobotRecord.angle = rpy ? rpy[2] : 0
      realtimeInfo.coordinates = `(${xyz[0]},${xyz[1]},${xyz[2] || 0})`
    }

    if (rpy) {
      realtimeInfo.heading = rpy[2] + '°'
    }

    if (pose.heading || pose.velocity) {
      realtimeInfo.speed = (pose.heading || 0) + 'm/s'
      realtimeInfo.speedCommand = (pose.velocity || 0) + 'm/s'
    }

    if (pose.odometer !== undefined) {
      realtimeInfo.totalDistance = pose.odometer + 'm'
    }

    if (pose.confidence !== undefined) {
      realtimeInfo.registrationError = pose.confidence
    }
  } catch (error) {
    console.error('解析位姿消息失败:', error)
  }
}

const handleBatteryMessage = (data) => {
  try {
    const payload = data.payload || data
    if (payload.capacity !== undefined) {
      realtimeInfo.batteryLevel = (payload.capacity * 100).toFixed(2) + '%'
    }
  } catch (error) {
    console.error('解析电池消息失败:', error)
  }
}

// === 工具栏事件处理 ===
const handleModeChange = (mode) => {
  const modeMap = {
    'select-mode': 'select',
    'draw-point': 'draw-point',
    'draw-line': 'draw-line',
    'draw-curve': 'draw-curve',
    'draw-polygon': 'draw-polygon'
  }

  const internalMode = modeMap[mode] || mode
  currentMode.value = mode
  const olmap = olmapRef.value

  switch (internalMode) {
    case 'select':
      pointDraSelectEnabled.value = true
      olmap?.clearDraw?.()
      ElMessage.success('已切换到选择模式')
      break
    case 'draw-point':
      pointDraSelectEnabled.value = false
      if (olmap?.drawPoint) {
        olmap.drawPoint()
        ElMessage.success('已切换到绘点模式，点击地图添加点位')
      } else {
        ElMessage.warning('地图组件未就绪，请稍后重试')
      }
      break
    case 'draw-line':
      pointDraSelectEnabled.value = false
      if (olmap?.drawLine) {
        olmap.drawLine()
        ElMessage.success('已切换到绘线模式，点击地图绘制线段')
      } else {
        ElMessage.warning('地图组件未就绪，请稍后重试')
      }
      break
    case 'draw-curve':
      pointDraSelectEnabled.value = false
      if (olmap?.drawCurve) {
        olmap.drawCurve()
        ElMessage.success('已切换到绘曲线模式，点击地图绘制曲线')
      } else {
        ElMessage.warning('地图组件未就绪，请稍后重试')
      }
      break
    case 'draw-polygon':
      pointDraSelectEnabled.value = false
      if (olmap?.drawPolygon) {
        olmap.drawPolygon()
        ElMessage.success('已切换到绘区域模式，点击地图绘制多边形区域')
      } else {
        ElMessage.warning('地图组件未就绪，请稍后重试')
      }
      break
    default:
      console.warn('未知的绘制模式:', mode)
      break
  }
}

const handleZoomIn = () => {
  const olmap = olmapRef.value
  if (olmap?.map) {
    const view = olmap.map.getView()
    view.animate({ zoom: view.getZoom() + 1, duration: 250 })
  }
}

const handleZoomOut = () => {
  const olmap = olmapRef.value
  if (olmap?.map) {
    const view = olmap.map.getView()
    view.animate({ zoom: view.getZoom() - 1, duration: 250 })
  }
}

const handleCenterRobot = () => {
  const olmap = olmapRef.value
  if (olmap?.map && robotPoseData.x && robotPoseData.y) {
    const view = olmap.map.getView()
    view.animate({
      center: [robotPoseData.x, robotPoseData.y],
      duration: 300
    })
  }
}

const handleToggleFullscreen = () => {
  if (!document.fullscreenElement) {
    document.documentElement.requestFullscreen()
  } else {
    document.exitFullscreen()
  }
}

const handleSaveMap = async () => {
  if (!haveDraw.value && resourcesFeature.value.length > 0) {
    ElMessage.info('当前没有需要保存的更改')
    return
  }

  if (resourcesFeature.value.length === 0) {
    ElMessage.warning('当前地图没有任何元素可保存')
    return
  }

  try {
    ElMessage.info('正在保存路网数据...')
    await saveRoute()
  } catch (error) {
    console.error('保存失败:', error)
  }
}

// === 右侧面板事件处理 ===
const handleAddCurrentPoint = () => {
  addCurrentMapShow.value = true
}

const handleElementSelect = (element) => {
  showInspector(element, 'edit')
  const olmap = olmapRef.value
  if (olmap?.selectShowEle && element?.id) {
    olmap.selectShowEle(element.id)
  }
}

const handleElementEdit = (element) => {
  const olmap = olmapRef.value
  if (olmap?.selectShowEle && element?.id) {
    olmap.selectShowEle(element.id)
  }
  showInspector(element, 'edit')
}

const handleElementLocate = (element) => {
  const olmap = olmapRef.value
  if (olmap?.selectShowEle && element?.id) {
    olmap.selectShowEle(element.id)
    ElMessage.success(`已定位到元素 ${element.id}`)
  } else {
    ElMessage.error('无法定位元素')
  }
}

const handleElementRemove = async (element) => {
  try {
    await ElMessageBox.confirm(`确定要删除元素 ${element.id} 吗？`, '确认删除', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })

    const loading = ElLoading.service({
      lock: true,
      text: '正在删除元素...',
      spinner: 'el-icon-loading',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    try {
      const olmap = olmapRef.value
      if (olmap?.removeElement) {
        olmap.removeElement(element.id)
      }

      await saveRoute()

      if (inspector.visible && inspector.data && inspector.data.id === element.id) {
        inspector.visible = false
        inspector.mode = 'view'
        inspector.data = null
      }

      ElMessage.success(`元素 ${element.id} 删除成功`)
    } finally {
      loading.close()
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除元素失败:', error)
      ElMessage.error('删除元素失败: ' + (error.message || '未知错误'))
    }
  }
}

// === 路网导入导出 ===
const handleNetworkExport = async () => {
  try {
    if (!resourcesFeature.value || resourcesFeature.value.length === 0) {
      ElMessage.warning('当前地图没有路网数据可导出')
      return
    }

    const loading = ElLoading.service({
      lock: true,
      text: '正在准备导出数据...',
      spinner: 'el-icon-loading',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    try {
      const geoJsonData = buildGeoJsonData()

      const exportData = {
        ...geoJsonData,
        metadata: {
          exportTime: new Date().toISOString(),
          mapName: mapName.value,
          elementCount: geoJsonData.features.length,
          version: '1.0'
        }
      }

      const fileContent = JSON.stringify(exportData, null, 2)
      const blob = new Blob([fileContent], { type: 'application/json' })

      const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)
      const fileName = `roadmap_${mapName.value}_${timestamp}.json`

      const url = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = url
      link.download = fileName

      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)

      window.URL.revokeObjectURL(url)

      ElMessage.success(`路网数据已导出：${fileName}`)
    } finally {
      loading.close()
    }
  } catch (error) {
    console.error('路网导出失败:', error)
    ElMessage.error('路网导出失败：' + (error.message || '未知错误'))
  }
}

const handleNetworkImport = (type) => {
  const fileInput = document.createElement('input')
  fileInput.type = 'file'
  fileInput.accept = '.json'
  fileInput.style.display = 'none'

  fileInput.addEventListener('change', async (event) => {
    const file = event.target.files[0]
    if (!file) return

    try {
      await processImportFile(file, type)
    } catch (error) {
      console.error('导入处理失败:', error)
      ElMessage.error(`路网导入失败：` + (error.message || '未知错误'))
    } finally {
      document.body.removeChild(fileInput)
    }
  })

  document.body.appendChild(fileInput)
  fileInput.click()
}

const processImportFile = async (file, importType) => {
  const typeMap = {
    'import': '导入',
    'replace': '覆盖导入',
    'merge': '合并导入',
    'incremental': '增量导入'
  }

  const loading = ElLoading.service({
    lock: true,
    text: `正在${typeMap[importType] || '导入'}路网数据...`,
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    const fileContent = await readFileContent(file)

    let importData
    try {
      importData = JSON.parse(fileContent)
    } catch (parseError) {
      throw new Error('文件格式错误：无法解析JSON数据')
    }

    validateImportData(importData)
    await executeImportStrategy(importData, importType)
    await refreshMapAfterImport()
    await saveRoute()

    ElMessage.success(`路网${typeMap[importType] || '导入'}成功！共处理${importData.features.length}个元素`)
  } finally {
    loading.close()
  }
}

const readFileContent = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = e => resolve(e.target.result)
    reader.onerror = () => reject(new Error('文件读取失败'))
    reader.readAsText(file)
  })
}

const validateImportData = (data) => {
  if (!data || typeof data !== 'object') {
    throw new Error('无效的数据格式')
  }

  if (data.type !== 'FeatureCollection') {
    throw new Error('数据类型错误：期望FeatureCollection格式')
  }

  if (!Array.isArray(data.features)) {
    throw new Error('数据格式错误：缺少features数组')
  }

  if (data.features.length === 0) {
    throw new Error('导入文件中没有路网元素')
  }
}

const executeImportStrategy = async (importData, importType) => {
  const features = importData.features

  switch (importType) {
    case 'replace':
      await replaceImport(features)
      break
    case 'merge':
      await mergeImport(features)
      break
    case 'incremental':
      await incrementalImport(features)
      break
    default:
      await normalImport(features)
      break
  }
}

const replaceImport = async (features) => {
  clearAllMapElements()
  await importFeaturesToMap(features)
}

const mergeImport = async (features) => {
  await importFeaturesToMap(features)
}

const incrementalImport = async (features) => {
  const newFeatures = features.filter(feature => {
    return !resourcesFeature.value.find(f => f.getId() === feature.properties.id)
  })

  if (newFeatures.length === 0) {
    ElMessage.info('所有元素均已存在，无需导入')
    return
  }

  await importFeaturesToMap(newFeatures)
  ElMessage.info(`跳过${features.length - newFeatures.length}个已存在的元素`)
}

const normalImport = async (features) => {
  await importFeaturesToMap(features)
}

const clearAllMapElements = () => {
  const olmap = olmapRef.value
  if (olmap?.clearAllElements) {
    olmap.clearAllElements()
  }

  pointData.value = []
  lineData.value = []
  bowData.value = []
  shapeData.value = []
  resourcesFeature.value = []
  currentFeature.value = {}
}

const importFeaturesToMap = async (features) => {
  const olmap = olmapRef.value
  if (!olmap?.importGeoJsonFeatures) {
    throw new Error('地图组件未就绪，无法导入数据')
  }

  const geoJsonData = {
    type: 'FeatureCollection',
    features: features
  }

  await olmap.importGeoJsonFeatures(geoJsonData)
}

const refreshMapAfterImport = async () => {
  await nextTick()

  const olmap = olmapRef.value
  if (olmap?.refresh) {
    olmap.refresh()
  }
}

// === Inspector事件处理 ===
const showInspector = (element, mode = 'edit') => {
  inspector.loading = true
  inspector.visible = true
  inspector.mode = mode

  setTimeout(() => {
    const elementData = prepareElementData(element)
    inspector.data = elementData
    inspector.loading = false
    currentFeature.value = element
  }, 100)
}

const prepareElementData = (element) => {
  const feature = resourcesFeature.value.find(f => f.getId() === element.id)
  if (feature) {
    const properties = feature.getProperties()
    const geometry = feature.getGeometry()

    return {
      ...element,
      ...properties,
      type: geometry.getType(),
      position: geometry.getType() === 'Point' ? geometry.getCoordinates() : undefined
    }
  }
  return element
}

const handleInspectorEdit = () => {
  inspector.mode = 'edit'
}

const handleInspectorSave = async (elementData) => {
  const olmap = olmapRef.value

  if (!elementData || !elementData.id) {
    ElMessage.error('保存失败：元素数据无效')
    return
  }

  if (!resourcesFeature.value || resourcesFeature.value.length === 0) {
    ElMessage.error('保存失败：找不到地图元素数据')
    return
  }

  const loading = ElLoading.service({
    lock: true,
    text: '正在保存元素...',
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    let targetFeature = null
    for (let i = 0; i < resourcesFeature.value.length; i++) {
      if (resourcesFeature.value[i].getId() === elementData.id) {
        targetFeature = resourcesFeature.value[i]
        break
      }
    }

    if (!targetFeature) {
      throw new Error(`找不到ID为 ${elementData.id} 的元素`)
    }

    const cleanData = { ...elementData }
    delete cleanData.typeEle
    delete cleanData.directList

    targetFeature.setProperties(cleanData)

    if (elementData.position && targetFeature.getGeometry().getType() === 'Point') {
      targetFeature.getGeometry().setCoordinates(elementData.position)
      if (olmap?.pointPositionUpdate && elementData.id) {
        olmap.pointPositionUpdate(elementData.id, elementData.position)
      }
    }

    if (elementData.id && elementData.id.startsWith('s')) {
      if (olmap?.editSnapeColor) {
        olmap.editSnapeColor(elementData.id)
      }
    }

    currentFeature.value = { ...elementData }
    haveDraw.value = true

    updateElementInList(elementData)
    await saveRoute()

    inspector.visible = false

    setTimeout(() => {
      if (olmap?.selectShowEle && elementData.id) {
        olmap.selectShowEle(elementData.id)
      }
    }, 100)

    ElMessage.success(`元素 ${elementData.id} 保存成功`)
  } catch (error) {
    console.error('保存元素失败:', error)
    ElMessage.error('保存元素失败: ' + (error.message || '未知错误'))
  } finally {
    loading.close()
  }
}

const handleInspectorCancel = () => {
  inspector.visible = false
  inspector.mode = 'view'
}

const handleInspectorClose = () => {
  inspector.visible = false
  inspector.mode = 'view'
  inspector.data = null
}

const handleInspectorLocate = (element) => {
  const olmap = olmapRef.value
  if (olmap?.selectShowEle && element?.id) {
    olmap.selectShowEle(element.id)
  }
}

const handleInspectorHeightChange = (height) => {
  console.log('Inspector高度变化为:', height)
}

const updateElementInList = (elementData) => {
  const updateElementInArray = (array) => {
    const index = array.findIndex(item => item.id === elementData.id)
    if (index !== -1) {
      array[index] = { ...array[index], ...elementData }
    }
  }

  if (elementData.id.startsWith('p')) {
    updateElementInArray(pointData.value)
  } else if (elementData.id.startsWith('l')) {
    updateElementInArray(lineData.value)
  } else if (elementData.id.startsWith('b')) {
    updateElementInArray(bowData.value)
  } else if (elementData.id.startsWith('s')) {
    updateElementInArray(shapeData.value)
  }
}

// === 地图事件处理 ===
const resourcesFeature = ref([])

const elementRoadInitEnd = (features) => {
  features.forEach(item => {
    if (item.values_ && item.values_.id) {
      const id = item.values_.id
      const data = {
        id: id,
        name: item.values_.name,
        type: item.getGeometry().getType()
      }
      if (id.startsWith('p')) {
        pointData.value.push(data)
      } else if (id.startsWith('l')) {
        lineData.value.push(data)
      } else if (id.startsWith('b')) {
        bowData.value.push(data)
      } else if (id.startsWith('s')) {
        shapeData.value.push(data)
      }
    }
  })

  pointData.value.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]))
  lineData.value.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]))
  bowData.value.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]))
  shapeData.value.sort((a, b) => parseInt(a.id.split('_')[1]) - parseInt(b.id.split('_')[1]))

  resourcesFeature.value = features.filter(feature => feature !== null && feature !== undefined && typeof feature.getGeometry === 'function')
  console.log(`elementRoadInitEnd: 原始feature数量=${features.length}, 有效feature数量=${resourcesFeature.value.length}`)
}

const elementRoadDrawEnd = (feature) => {
  const id = feature.values_.id || feature.getId()
  const data = {
    id: id,
    name: feature.values_.name,
    type: feature.getGeometry().getType()
  }
  if (id.startsWith('p')) {
    pointData.value.push(data)
    initElelmentParamsPonint(feature)
  } else if (id.startsWith('l')) {
    lineData.value.push(data)
    initElelmentParamsBowOrLine(feature)
  } else if (id.startsWith('b')) {
    bowData.value.push(data)
    initElelmentParamsBowOrLine(feature)
  } else if (id.startsWith('s')) {
    shapeData.value.push(data)
    initElelmentParamsSnape(feature)
  }
  haveDraw.value = true
}

const selectShowEleResult = (feature) => {
  const geometry = feature.getGeometry()

  if (geometry.getType() == 'Point') {
    feature.set('position', geometry.getCoordinates())
  } else if (geometry.getType() == "LineString") {
    const value = feature.values_.direct - 100 || 0
    const binary = value.toString(2).padStart(4, '0')
    const result = [
      binary[0] === '1',
      binary[1] === '1',
      binary[2] === '1',
      binary[3] === '1'
    ]
    feature.set('directList', result)
  }
  feature.set('typeEle', geometry.getType())

  const elementData = {
    id: feature.getId(),
    name: feature.get('name') || '',
    type: geometry.getType(),
    ...feature.getProperties()
  }

  showInspector(elementData, 'edit')
}

const removeElementResult = (id) => {
  if (!id) {
    ElMessage.error('移除元素失败!')
    return
  }

  if (id.startsWith('p')) {
    const index = pointData.value.findIndex(item => item.id === id)
    if (index !== -1) {
      pointData.value.splice(index, 1)
    }
  }
  if (id.startsWith('l')) {
    const index = lineData.value.findIndex(item => item.id === id)
    if (index !== -1) {
      lineData.value.splice(index, 1)
    }
  }
  if (id.startsWith('b')) {
    const index = bowData.value.findIndex(item => item.id === id)
    if (index !== -1) {
      bowData.value.splice(index, 1)
    }
  }
  if (id.startsWith('s')) {
    const index = shapeData.value.findIndex(item => item.id === id)
    if (index !== -1) {
      shapeData.value.splice(index, 1)
    }
  }

  if (currentFeature.value && currentFeature.value.id == id) {
    currentFeature.value = {}
  }

  const index = resourcesFeature.value.findIndex(feature => feature && feature.getId && feature.getId() == id)
  if (index !== -1) {
    resourcesFeature.value.splice(index, 1)
  }

  resourcesFeature.value = resourcesFeature.value.filter(feature => feature !== null && feature !== undefined && typeof feature.getGeometry === 'function')

  haveDraw.value = true
}

const initElelmentParamsPonint = (feature) => {
  feature.set('name', '')
  feature.set('yaw', 0)
  feature.set('isyawfix', feature.get('isyawfix') ? true : false)
  feature.set('taskid', 0)
  feature.set('offset', 0)
  feature.set('pitch', 0)
  feature.set('roll', 0)

  if (feature && typeof feature.getGeometry === 'function') {
    resourcesFeature.value.push(feature)
  }
}

const initElelmentParamsBowOrLine = (feature) => {
  feature.set('name', '')
  feature.set('direct', 110)
  feature.set('chassistype', 10)
  feature.set('plantype', 0)
  feature.set('controltype', 0)
  feature.set('obstype', 0)
  feature.set('runtype', 0)
  feature.set('roadwidth', 0)
  feature.set('lanewidth', 1.0)
  feature.set('leftlanenum', 0)
  feature.set('rightlanenum', 0)
  feature.set('maxspeed', 0.5)
  feature.set('minspeed', 0.0)
  feature.set('maxtheta', 1.0)
  feature.set('mintheta', -1.0)
  feature.set('selftheta', 0.5)
  feature.set('xytolerance', 0.2)
  feature.set('thtolerance', 0.2)
  feature.set('slowdis', 2.0)
  feature.set('followdis', 0.4)
  feature.set('obsvalue', 200)
  feature.set('s2eforward', 0.0)
  feature.set('e2sforward', 0.0)

  if (feature && typeof feature.getGeometry === 'function') {
    resourcesFeature.value.push(feature)
  }
}

const initElelmentParamsSnape = (feature) => {
  feature.set('name', '')
  feature.set('typeEle', feature.getGeometry().getType())
  feature.set('color', "#7EFFFA")
  feature.set('type', 1)
  feature.set('transparent', 200)

  if (feature && typeof feature.getGeometry === 'function') {
    resourcesFeature.value.push(feature)
  }
}

// === 保存路网 ===
const saveRoute = async () => {
  try {
    const geoJsonData = buildGeoJsonData()

    await saveRoadMapToServer(geoJsonData)

    haveDraw.value = false

    if (geoJsonData.features.length === 0) {
      ElMessage.success('路网已清空并保存')
    } else {
      ElMessage.success(`路网数据保存成功，共${geoJsonData.features.length}个元素`)
    }
  } catch (error) {
    console.error('保存路网数据失败:', error)
    ElMessage.error('保存路网数据失败: ' + (error.message || '未知错误'))
    throw error
  }
}

const cleanCoordinates = (coordinates) => {
  if (!coordinates) return coordinates

  if (Array.isArray(coordinates)) {
    return coordinates.map(coord => {
      if (Array.isArray(coord)) {
        return cleanCoordinates(coord)
      } else {
        return (coord === null || coord === undefined) ? 0 : coord
      }
    })
  }

  return coordinates
}

const buildGeoJsonData = () => {
  // 验证resourcesFeature数组
  if (!resourcesFeature.value || resourcesFeature.value.length === 0) {
    console.warn('buildGeoJsonData: resourcesFeature数组为空')
    return {
      type: "FeatureCollection",
      features: [],
      map: mapName.value
    }
  }

  console.log('构建GeoJSON数据，元素数量:', resourcesFeature.value.length)

  // 首先过滤掉null或undefined的feature对象
  const validFeatures = resourcesFeature.value.filter(feature => feature !== null && feature !== undefined)
  console.log('有效元素数量:', validFeatures.length)

  const features = validFeatures.map(feature => {
    try {
      // 再次确认feature是有效的
      if (!feature || typeof feature.getProperties !== 'function') {
        console.warn('发现无效的feature对象:', feature)
        return null
      }

      const properties = { ...feature.getProperties() }
      const geometry = feature.getGeometry()

      // 验证几何对象
      if (!geometry) {
        console.warn('发现无效的几何对象，跳过元素:', feature.getId())
        return null
      }

      // 确保包含ID
      if (!properties.id) {
        properties.id = feature.getId()
      }

      // 清理临时渲染属性（不修改原始数据，只在保存时清理）
      const cleanProperties = { ...properties }
      // 先保存贝塞尔控制点，因为后续处理需要用到
      const bezierControlPoints = cleanProperties.bezierControlPoints
      delete cleanProperties.typeEle      // 删除临时类型属性
      delete cleanProperties.position     // 删除临时位置属性
      delete cleanProperties.directList   // 删除临时方向列表属性
      delete cleanProperties.geometry     // 删除OpenLayers几何对象，避免嵌套
      // 注意：不在此处删除bezierControlPoints，让它保留在cleanProperties中用于后续处理

      // 删除可能存在的错误type字段（LineString/Point等）
      // 这个字段可能来自历史数据，会干扰导航算法
      // 注意：Polygon的type字段是合法的区域类型（0-22），不应删除
      if (geometry.getType() !== 'Polygon' && cleanProperties.type !== undefined) {
        console.warn(`删除元素 ${properties.id} 中的错误type字段:`, cleanProperties.type)
        delete cleanProperties.type
      }

      // 获取原始坐标并清理null值
      const originalCoordinates = geometry.getCoordinates()
      const cleanedCoordinates = cleanCoordinates(originalCoordinates)

      // 根据几何类型处理线段导出
      let exportGeometryType = geometry.getType()
      let exportCoordinates = cleanedCoordinates

      // 处理LineString类型的元素
      if (geometry.getType() === 'LineString') {
        const featureId = properties.id

        if (featureId && featureId.startsWith('b_')) {
          // 贝塞尔曲线：导出为MultiPoint，使用保存的完整控制点
          exportGeometryType = 'MultiPoint'

          // 优先使用保存的原始控制点（bezierControlPoints属性）
          if (bezierControlPoints && Array.isArray(bezierControlPoints)) {
            exportCoordinates = cleanCoordinates(bezierControlPoints)
            console.log(`贝塞尔曲线 ${featureId} 转换: LineString(${cleanedCoordinates.length}点) -> MultiPoint(${exportCoordinates.length}控制点)`)
          } else {
            // 兼容旧数据：如果没有保存控制点，只使用起点和终点
            exportCoordinates = [
              cleanedCoordinates[0],  // 起点
              cleanedCoordinates[cleanedCoordinates.length - 1]  // 终点
            ]
            console.warn(`贝塞尔曲线 ${featureId} 缺少控制点数据，只保存起点和终点`)
          }
        } else {
          // 普通LineString：只保存起点和终点
          // 避免中间可能被错误插入的顶点影响导航
          exportGeometryType = 'LineString'
          exportCoordinates = [
            cleanedCoordinates[0],  // 起点
            cleanedCoordinates[cleanedCoordinates.length - 1]  // 终点
          ]
          console.log(`普通线段 ${featureId} 优化: LineString(${cleanedCoordinates.length}点) -> LineString(2点)`)
        }
      }

      // 修复Point坐标：确保Point类型有3个坐标值（x, y, z）
      if (exportGeometryType === 'Point' && exportCoordinates.length === 2) {
        exportCoordinates.push(0.0) // 添加z坐标
      }

      return {
        type: "Feature",
        properties: cleanProperties,
        geometry: {
          type: exportGeometryType,
          coordinates: exportCoordinates
        }
      }
    } catch (error) {
      console.error('处理元素时出错:', feature.getId(), error)
      return null
    }
  }).filter(feature => feature !== null) // 过滤掉无效的元素

  const result = {
    type: "FeatureCollection",
    features: features,
    map: mapName.value
  }

  console.log('构建完成，有效元素数量:', features.length)
  return result
}

const saveRoadMapToServer = async (geoJsonData) => {
  try {
    const response = await saveRoadMapGeoJson(geoJsonData)

    if (response && response.status === true) {
      return response
    } else {
      throw new Error('保存失败：服务器返回状态为false')
    }
  } catch (error) {
    console.error('保存路网数据失败:', error)
    throw error
  }
}

// === 添加当前点对话框处理 ===
const openCurrentToMapDialog = () => {
  currentRobotRecord.x = robotPoseData.x || 0
  currentRobotRecord.y = robotPoseData.y || 0
  currentRobotRecord.z = 0
  currentRobotRecord.angle = robotPoseData.angle || 0
  currentRobotRecord.angleEnable = false
}

const addCurrentToMap = async () => {
  const formEl = currentPointFormRef.value
  if (!formEl) return

  try {
    await formEl.validate()
    addCurrentMapShow.value = false
    const data = [
      { yaw: currentRobotRecord.angle },
      { isyawfix: currentRobotRecord.angleEnable }
    ]
    const olmap = olmapRef.value
    olmap?.createPointAtCoordinateForImport?.(
      [currentRobotRecord.x, currentRobotRecord.y, currentRobotRecord.z || 0],
      '',
      data
    )
    ElMessage.success('已添加当前位姿点到地图')
  } catch {
    // 验证失败，不做任何操作
  }
}

// === Route Leave Guard ===
import { onBeforeRouteLeave } from 'vue-router'

onBeforeRouteLeave((to, from) => {
  const inspectorRef = bottomInspectorRef.value
  const inspectorHasChanges = inspector.visible && inspector.mode === 'edit' && inspectorRef?.hasUnsavedChanges

  if (haveDraw.value || inspectorHasChanges) {
    const message = inspectorHasChanges
      ? 'Inspector中有未保存的元素更改，确定要跳转或退出?'
      : '当前页面的地图修改还未保存,确定要跳转或退出?'

    return ElMessageBox.confirm(message, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      inspector.visible = false
      return true
    }).catch(() => {
      return false
    })
  }
  return true
})

// === Lifecycle ===
onMounted(() => {
  updateMapSize()
  initEditMode()
  updateRightWidth(380)
  window.addEventListener('resize', updateMapSize)
  window.addEventListener("beforeunload", handleBeforeUnload)

  // 初始化WebSocket连接
    setupWebSocket()
})

onBeforeUnmount(() => {
  window.removeEventListener("beforeunload", handleBeforeUnload)
  window.removeEventListener('resize', updateMapSize)
  // 断开WebSocket连接
  disconnect()
})
</script>

<style lang="scss" scoped>
@import '../components/shared/_map-shared.css';

.edit-page {
  height: calc(100vh - 84px);
  display: flex;
  flex-direction: column;
  background: #f5f7fa;
  position: relative;
  overflow: hidden;

  --left-safe: 88px;
  --right-panel-width: 380px;
  --right-gutter: 32px;
  --right-safe: calc(var(--right-panel-width) + var(--right-gutter));
}

.map-container {
  flex: 1;
  display: flex;
  position: relative;
  min-height: 0;
}

.toolbar-container {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 11;
  pointer-events: none;

  > * {
    pointer-events: auto;
  }
}

#map-stage {
  flex: 1;
  position: relative;
  background: #f5f5f5;
  overflow: hidden;
}

.panel-container {
  // 编辑页面板现在使用 fixed 定位，容器不需要特殊样式
  pointer-events: none;
  
  > * {
    pointer-events: auto;
  }
}

// 对话框样式优化
:deep(.el-dialog) {
  border-radius: 12px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);

  .el-dialog__header {
    padding: 20px 24px 10px;
    border-bottom: 1px solid #e4e7ed;

    .el-dialog__title {
      font-size: 18px;
      font-weight: 600;
      color: #303133;
    }
  }

  .el-dialog__body {
    padding: 20px 24px;
  }

  .el-dialog__footer {
    padding: 10px 24px 20px;
    text-align: right;

    .el-button {
      margin-left: 12px;

      &:first-child {
        margin-left: 0;
      }
    }
  }
}

// 表单样式优化
:deep(.el-form) {
  .el-form-item {
    margin-bottom: 18px;

    .el-form-item__label {
      font-weight: 500;
      color: #374151;
      line-height: 1.6;
    }

    .el-form-item__content {
      line-height: 1.6;
    }
  }

  .el-input {
    .el-input__inner {
      border-radius: 8px;
      border: 1px solid #d1d5db;
      transition: all 0.2s ease;

      &:focus {
        border-color: #3b82f6;
        box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
      }
    }
  }

  .el-input-number {
    width: 100%;

    .el-input__inner {
      border-radius: 8px;
      border: 1px solid #d1d5db;
      text-align: left;

      &:focus {
        border-color: #3b82f6;
        box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
      }
    }
  }

  .el-switch {
    .el-switch__core {
      border-radius: 12px;
    }
  }
}

.centered-dialog {
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
}

.add-pose-dialog {
  :deep(.el-dialog) {
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
    margin: 0 auto;
    position: relative;
    top: 50%;
    transform: translateY(-50%);
    max-height: 90vh;
    overflow-y: auto;
  }

  :deep(.el-dialog__wrapper) {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
  }

  :deep(.el-dialog) {
    margin-top: 0 !important;
    margin-bottom: 0 !important;
  }

  :deep(.el-dialog__header) {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    padding: 20px 24px;
    margin: 0;
    border-radius: 12px 12px 0 0;

    .el-dialog__title {
      color: white;
      font-size: 18px;
      font-weight: 600;
    }

    .el-dialog__close {
      color: white;
      font-size: 18px;

      &:hover {
        color: #f0f0f0;
      }
    }
  }

  :deep(.el-dialog__body) {
    padding: 24px;
    background: #f8fafc;
    margin: 0;
    max-height: calc(90vh - 120px);
    overflow-y: auto;
  }

  :deep(.el-dialog__footer) {
    padding: 16px 24px 24px;
    background: #f8fafc;
    border-top: 1px solid #e2e8f0;
    border-radius: 0 0 12px 12px;
    margin: 0;
  }
}

.pose-form {
  .el-form-item {
    margin-bottom: 14px;
    display: flex;
    align-items: center;

    &:last-child {
      margin-bottom: 0;
    }

    .el-form-item__content {
      flex: 1;
      margin-left: 0;
    }
  }

  .coordinate-input {
    margin-bottom: 4px;
  }

  .el-form-item__label {
    font-weight: 600;
    color: #2d3748;
    padding-right: 12px;
    min-width: 100px;
    font-size: 14px;
    line-height: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    margin-bottom: 0;
  }

  .coordinate-input {
    :deep(.el-input__inner) {
      border-radius: 8px;
      border: 1px solid #e2e8f0;
      height: 44px;
      font-size: 15px;
      padding: 0 16px;
      background: #ffffff;
      transition: all 0.2s ease;

      &:focus {
        border-color: #667eea;
        box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
        background: #fafbff;
      }

      &:hover {
        border-color: #cbd5e0;
      }
    }
  }

  :deep(.el-input-number) {
    width: 100%;

    .el-input__inner {
      border-radius: 6px;
      border: 1px solid #e2e8f0;
      height: 40px;
      font-size: 14px;
      padding: 0 12px;

      &:focus {
        border-color: #667eea;
        box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
      }
    }
  }
}

.dialog-content {
  .form-section {
    background: white;
    border-radius: 10px;
    padding: 20px;
    margin-bottom: 16px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    border: 1px solid #f1f5f9;

    &:last-child {
      margin-bottom: 0;
    }

    .section-title {
      display: flex;
      align-items: center;
      margin: 0 0 16px 0;
      font-size: 15px;
      font-weight: 600;
      color: #2d3748;
      border-bottom: 2px solid #e2e8f0;
      padding-bottom: 8px;

      .el-icon {
        margin-right: 10px;
        color: #667eea;
        font-size: 18px;
      }
    }
  }
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
// 响应式适配
@media (max-width: 1200px) {
  .panel-container {
    right: 8px;
    top: 8px;
  }
  
  .toolbar-container {
    left: 8px;
    top: 8px;
  }
}

@media (max-width: 768px) {
  .edit-page {
    .map-container {
	flex-direction: column;
    }
    
    .panel-container {
      position: relative;
      top: auto;
      right: auto;
	width: 100%;
      z-index: auto;
    }
    
    .toolbar-container {
	position: relative;
      top: auto;
      left: auto;
      z-index: auto;
	margin-bottom: 8px;
    }
  }
}

.edit-page {
  animation: fadeInUp 0.3s ease-out;
}
</style>
