<template>
  <el-dialog
      :title="title"
      v-model="dialogVisible"
      width="80%"
      destroy-on-close
      @opened="handleDialogOpened"
      @closed="handleDialogClosed"
  >
    <div v-loading="mapLoading" element-loading-text="地图加载中..." class="map-dialog-container">
      <!-- 交通方式选择 -->
      <div class="transport-controls">
        <el-button :type="activeTransport === 'walk' ? 'primary' : ''" @click="planWalkingRoute">步行</el-button>
        <el-button :type="activeTransport === 'drive' ? 'primary' : ''" @click="planDrivingRoute">驾车</el-button>
        <el-button :type="activeTransport === 'bike' ? 'primary' : ''" @click="planBikingRoute">骑行</el-button>
      </div>

      <!-- 路线摘要 -->
      <div v-if="routeResult" class="route-summary">
        <div><i class="el-icon-location"></i> 起点: {{ startAddressDisplay }}</div>
        <div><i class="el-icon-location-outline"></i> 终点: {{ endAddressDisplay }}</div>
        <div><i class="el-icon-time"></i> {{ routeResult.summary }}</div>
      </div>

      <!-- 地图容器 -->
      <div :id="mapContainerId" class="map-container"></div>

      <!-- 路线详情面板 -->
      <div :id="routeContainerId" class="route-details"></div>
    </div>

    <template #footer>
      <el-button @click="dialogVisible = false">关闭</el-button>
    </template>
  </el-dialog>
</template>

<script>
import { ref, reactive, onMounted, watch, toRefs, onUnmounted, nextTick } from "vue";
import { ElMessage } from "element-plus";

export default {
  name: "PathPlanning",
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: "订单配送路线规划"
    },
    startAddress: {
      type: String,
      default: ""
    },
    endAddress: {
      type: String,
      default: ""
    }
  },
  emits: ["update:visible", "route-complete"],
  setup(props, { emit }) {
    // 状态管理
    const dialogVisible = ref(props.visible);
    const mapLoading = ref(false);
    const mapContainerId = `map-container-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
    const routeContainerId = `route-container-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
    const isAMapLoaded = ref(false);
    const activeTransport = ref("drive");
    const startAddressDisplay = ref(props.startAddress);
    const endAddressDisplay = ref(props.endAddress);
    const myPosition = ref(null);
    const locating = ref(false);
    const locationError = ref("");
    const ipLocating = ref(false);
    const isLocationSet = ref(false); // 是否已设置定位

    // 地图相关变量
    let map = null;
    let geocoder = null;
    let walk = null;
    let drive = null;
    let bike = null;
    let geolocation = null; // 定位插件
    const eventListeners = [];

    // 路线规划结果
    const routeResult = ref(null);

    // 数据
    const state = reactive({
      AMAP_KEY: "2a1ea1e08e1fe8f6f550846c615aecd2",
      SECURITY_CODE: "ad0593c8a866e54628d5052f55342169",
      startAddress: props.startAddress,
      endAddress: props.endAddress
    });

    // 监听props变化
    watch(() => props.visible, (val) => {
      dialogVisible.value = val;
      if (val && props.startAddress && props.endAddress) {
        initMapWithRoute();
      }
    });

    watch(dialogVisible, (val) => {
      emit('update:visible', val);
    });

    watch(() => props.startAddress, (newVal) => {
      state.startAddress = newVal;
      startAddressDisplay.value = newVal;
      if (dialogVisible.value && props.endAddress) {
        planRoute();
      }
    });

    watch(() => props.endAddress, (newVal) => {
      state.endAddress = newVal;
      endAddressDisplay.value = newVal;
      if (dialogVisible.value && props.startAddress) {
        planRoute();
      }
    });

    // 对话框打开后初始化地图
    const handleDialogOpened = () => {
      nextTick(() => {
        if (!props.startAddress || !props.endAddress) {
          ElMessage.warning("缺少起点或终点地址");
          return;
        }
        initMapWithRoute();
      });
    };

    // 对话框关闭时清理资源
    const handleDialogClosed = () => {
      if (map) {
        map.destroy();
        map = null;
      }
      if (walk) {
        walk.clear();
        walk = null;
      }
      if (drive) {
        drive.clear();
        drive = null;
      }
      if (bike) {
        bike.clear();
        bike = null;
      }
      if (geolocation) {
        geolocation.clearWatch();
        geolocation = null;
      }
      eventListeners.forEach(listener => {
        if (listener.remove) listener.remove();
      });
      eventListeners.length = 0;
      isLocationSet.value = false;
    };

    // 组件卸载时清理资源
    onUnmounted(() => {
      handleDialogClosed();
    });

    // 带路线规划的地图初始化
    const initMapWithRoute = () => {
      if (isAMapLoaded.value) {
        initMap();
      } else {
        loadAMapScript();
      }
    };

    // 初始化地图
    const initMap = () => {
      mapLoading.value = true;
      locating.value = false;
      locationError.value = "";

      const container = document.getElementById(mapContainerId);
      if (!container) {
        console.error("地图容器不存在");
        mapLoading.value = false;
        return;
      }

      try {
        if (map) {
          map.destroy();
        }

        map = new AMap.Map(mapContainerId, {
          zoom: 13,
          resizeEnable: true,
          viewMode: "2D",
        });

        // 初始化定位插件
        initGeolocation();

        geocoder = new AMap.Geocoder({
          city: "全国"
        });

        initRoutePlanners();

        // 如果起点是"我的位置"，且尚未设置定位，则触发定位
        if (state.startAddress === "我的位置" && !isLocationSet.value) {
          getMyLocation();
        } else {
          planRoute();
        }

      } catch (error) {
        console.error("地图初始化异常:", error);
        mapLoading.value = false;
        ElMessage.error("地图初始化失败，请重试");
      }
    };

    // 初始化定位插件（终极修复版）
    const initGeolocation = () => {
      if (geolocation) {
        geolocation.clearWatch();
      }

      // 定义插件加载的Promise
      const loadGeolocationPlugin = new Promise((resolve) => {
        // 使用AMap.event监听插件加载完成
        if (window.AMap && window.AMap.event) {
          // 检查插件是否已加载
          if (window.AMap.Geolocation) {
            console.log('定位插件已加载');
            resolve();
            return;
          }

          // 监听插件加载事件
          const listener = window.AMap.event.addListener(window.AMap, 'PluginsLoaded', () => {
            if (window.AMap.Geolocation) {
              console.log('定位插件加载完成');
              resolve();
              window.AMap.event.removeListener(listener);
            }
          });
        } else {
          // AMap对象未加载时，等待AMap对象可用
          const checkAMap = setInterval(() => {
            if (window.AMap && window.AMap.event) {
              clearInterval(checkAMap);
              initGeolocation(); // 递归重试
            }
          }, 100);

          // 设置超时
          setTimeout(() => {
            clearInterval(checkAMap);
            console.error('AMap对象加载超时');
            locationError.value = "地图服务加载超时，请刷新页面";
          }, 10000);
        }
      });

      // 初始化定位插件
      loadGeolocationPlugin
          .then(() => {
            try {
              // 创建定位实例
              geolocation = new AMap.Geolocation({
                enableHighAccuracy: true,
                timeout: 10000,
                maximumAge: 0,
                convert: true,
                showButton: false,
                showMarker: false,
                showCircle: false,
                panToLocation: false,
                zoomToAccuracy: false,
                extensions: 'all'
              });

              // 将定位控件添加到地图
              if (map) {
                map.addControl(geolocation);
              }

              // 确保事件系统可用
              if (!AMap.event) {
                throw new Error('AMap事件系统未定义');
              }

              // 添加事件监听
              AMap.event.addListener(geolocation, 'complete', onLocationComplete);
              AMap.event.addListener(geolocation, 'error', onLocationError);

              console.log('定位插件初始化完成');
            } catch (error) {
              console.error('定位插件初始化异常:', error);
              locationError.value = "定位功能初始化失败，请刷新页面重试";
            }
          })
          .catch(error => {
            console.error('定位插件加载失败:', error);
            locationError.value = "定位功能初始化失败，请检查网络连接";
          });
    };

    // 定位成功回调
    const onLocationComplete = (data) => {
      locating.value = false;
      isLocationSet.value = true;

      console.log('定位成功:', data);

      if (data.position) {
        myPosition.value = data.position;

        // 更新起点地址显示
        if (data.formattedAddress) {
          startAddressDisplay.value = `我的位置（${data.formattedAddress}）`;
        } else if (data.addressComponent) {
          startAddressDisplay.value = `我的位置（${data.addressComponent.province}${data.addressComponent.city}）`;
        } else {
          startAddressDisplay.value = "我的位置";
        }

        // 如果起点是"我的位置"，自动规划路线
        if (state.startAddress === "我的位置") {
          planRoute();
        }
      }
    };

    // 定位失败回调
    const onLocationError = (err) => {
      locating.value = false;
      console.error('定位失败:', err);

      // 尝试使用IP定位作为备选方案
      if (err.info === 'FAILED' || err.info === 'TIMEOUT') {
        getIPLocation();
      } else {
        locationError.value = `定位失败: ${err.info}`;
        ElMessage.error(locationError.value);

        // 定位失败时，将起点设为默认位置（北京）
        startAddressDisplay.value = "我的位置（定位失败）";
      }
    };

    // 获取当前位置
    const getMyLocation = () => {
      if (!geolocation) {
        console.error('定位插件未初始化');
        locationError.value = "定位功能未就绪，请刷新页面重试";
        return;
      }

      locating.value = true;
      locationError.value = "";

      // 调用定位插件获取位置
      geolocation.getCurrentPosition();
    };

    // 备选方案：使用IP定位
    const getIPLocation = () => {
      ipLocating.value = true;

      // 尝试使用AMap.CitySearch获取IP定位
      AMap.plugin('AMap.CitySearch', () => {
        const citySearch = new AMap.CitySearch();

        citySearch.getLocalCity((status, result) => {
          ipLocating.value = false;

          if (status === 'complete') {
            console.log('IP定位成功:', result);

            if (result.bounds) {
              // 获取城市中心点
              const center = result.bounds.getCenter();
              myPosition.value = center;

              // 更新起点地址显示
              startAddressDisplay.value = `我的位置（${result.city}）`;

              // 如果起点是"我的位置"，自动规划路线
              if (state.startAddress === "我的位置") {
                planRoute();
              }
            }
          } else {
            console.error('IP定位失败:', result);
            locationError.value = "定位失败，无法获取位置信息";
            ElMessage.error(locationError.value);

            // 定位失败时，将起点设为默认位置（北京）
            startAddressDisplay.value = "我的位置（定位失败）";
          }
        });
      });
    };

    // 初始化路线规划器
    const initRoutePlanners = () => {
      if (!map) return;

      if (walk) walk.clear();
      if (drive) drive.clear();
      if (bike) bike.clear();

      walk = new AMap.Walking({
        map: map,
        panel: routeContainerId,
        hideMarkers: true
      });

      drive = new AMap.Driving({
        map: map,
        panel: routeContainerId,
        policy: AMap.DrivingPolicy.LEAST_TIME,
        hideMarkers: true,
        showTraffic: true
      });

      bike = new AMap.Riding({
        map: map,
        panel: routeContainerId,
        hideMarkers: true
      });
    };

    // 规划路线
    const planRoute = async (type = activeTransport.value) => {
      if (!geocoder || !state.startAddress || !state.endAddress) {
        return;
      }

      mapLoading.value = true;

      try {
        let startLngLat;
        if (state.startAddress === '我的位置') {
          // 如果尚未获取到位置，先等待定位
          if (!myPosition.value) {
            if (!locating.value && !ipLocating.value) {
              getMyLocation();
            }
            mapLoading.value = false;
            return;
          }
          startLngLat = myPosition.value;
        } else {
          // 地址解析
          startLngLat = await new Promise((resolve, reject) => {
            geocoder.getLocation(state.startAddress, (status, result) => {
              if (status === 'complete' && result.geocodes.length) {
                resolve(result.geocodes[0].location);
              } else {
                reject(new Error('起点地址解析失败'));
              }
            });
          });
        }

        // 终点地址解析
        const endLngLat = await new Promise((resolve, reject) => {
          geocoder.getLocation(state.endAddress, (status, result) => {
            if (status === 'complete' && result.geocodes.length) {
              resolve(result.geocodes[0].location);
            } else {
              reject(new Error('终点地址解析失败'));
            }
          });
        });

        // 计算距离
        const distance = calculateDistance(startLngLat, endLngLat);

        // 根据距离选择合适的路线规划方式
        if (type === 'walk' && distance > 20000) {
          ElMessage.warning("步行路线距离过长，请选择其他交通方式");
          activeTransport.value = 'drive';
          doPlanRoute(startLngLat, endLngLat, 'drive');
        } else if (type === 'bike' && distance > 50000) {
          ElMessage.warning("骑行路线距离过长，请选择其他交通方式");
          activeTransport.value = 'drive';
          doPlanRoute(startLngLat, endLngLat, 'drive');
        } else {
          doPlanRoute(startLngLat, endLngLat, type);
        }
      } catch (error) {
        mapLoading.value = false;
        ElMessage.error(error.message);
      }
    };

    // 计算两点之间的距离（米）
    const calculateDistance = (point1, point2) => {
      if (!point1 || !point2) return 0;
      return AMap.GeometryUtil.distance(point1, point2);
    };

    // 执行路线规划
    const doPlanRoute = (startLngLat, endLngLat, type) => {
      let planner;
      switch (type) {
        case "walk":
          planner = walk;
          break;
        case "drive":
          planner = drive;
          break;
        case "bike":
          planner = bike;
          break;
        default:
          planner = drive;
      }

      if (planner) {
        planner.clear();

        planner.search(
            startLngLat,
            endLngLat,
            (status, result) => {
              mapLoading.value = false;
              if (status === "complete") {
                // 路线规划成功
                const summary = formatRouteSummary(result);
                routeResult.value = {
                  summary: summary,
                  details: result
                };
                activeTransport.value = type;
                emit("route-complete", routeResult.value);
                map.setFitView();
              } else {
                // 错误处理
                const errorInfo = result && result.info ? result.info : "未知错误";
                console.error("路线规划失败:", errorInfo);

                if (errorInfo === "OVER_DIRECTION_RANGE") {
                  ElMessage.error("路线距离超出规划范围，请选择其他交通方式或调整起点终点");
                } else {
                  ElMessage.error("路线规划失败: " + errorInfo);
                }
              }
            }
        );
      } else {
        mapLoading.value = false;
        ElMessage.error("路线规划器未初始化，请重试");
      }
    };

    // 格式化路线摘要
    const formatRouteSummary = (result) => {
      if (!result || !result.routes || result.routes.length === 0) {
        return "暂无路线信息";
      }

      const route = result.routes[0];
      const distance = (route.distance / 1000).toFixed(1);
      const duration = Math.ceil(route.duration / 60);

      return `总距离: ${distance}公里，预计耗时: ${duration}分钟`;
    };

    // 规划步行路线
    const planWalkingRoute = () => {
      planRoute("walk");
    };

    // 规划驾车路线
    const planDrivingRoute = () => {
      planRoute("drive");
    };

    // 规划骑行路线
    const planBikingRoute = () => {
      planRoute("bike");
    };

    // 动态加载高德地图API
    const loadAMapScript = () => {
      if (isAMapLoaded.value) {
        initMap();
        return;
      }

      window._AMapSecurityConfig = {
        securityJsCode: state.SECURITY_CODE
      };

      const script = document.createElement("script");
      script.src = `https://webapi.amap.com/maps?v=2.0&key=${state.AMAP_KEY}&plugin=AMap.Geocoder,AMap.Walking,AMap.Driving,AMap.Riding,AMap.Geolocation,AMap.CitySearch`;
      script.onload = () => {
        console.log("高德地图API加载成功");
        isAMapLoaded.value = true;
        initMap();
      };
      script.onerror = () => {
        console.error("高德地图API加载失败");
        mapLoading.value = false;
        ElMessage.error("地图API加载失败，请检查网络连接或密钥是否正确");
      };
      document.head.appendChild(script);
    };

    return {
      ...toRefs(state),
      dialogVisible,
      mapLoading,
      mapContainerId,
      routeContainerId,
      handleDialogOpened,
      handleDialogClosed,
      planWalkingRoute,
      planDrivingRoute,
      planBikingRoute,
      routeResult,
      activeTransport,
      startAddressDisplay,
      endAddressDisplay,
      locating,
      locationError,
      ipLocating,
      getMyLocation
    };
  }
};
</script>

<style scoped>
.map-dialog-container {
  position: relative;
  height: 700px;
}

.map-container {
  height: 500px;
  width: 100%;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.route-details {
  height: 150px;
  overflow-y: auto;
  margin-top: 10px;
  padding: 10px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  background-color: #f8f9fa;
}

.transport-controls {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 999;
  background: white;
  padding: 8px;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.route-summary {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 999;
  background: rgba(255, 255, 255, 0.9);
  padding: 10px;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  max-width: 400px;
  font-size: 14px;
}

.route-summary div {
  margin-bottom: 5px;
  display: flex;
  align-items: center;
}

.route-summary i {
  margin-right: 5px;
  color: #409EFF;
}
</style>

为什么无法实现高德地图的自我定位功能