<template>
  <view class="map-container">
    <u-notice-bar mode="horizontal" :list="list"></u-notice-bar>
    <map id="map" class="map" :latitude="latitude" :longitude="longitude" :polygon="polygons" :markers="markers"
      :show-location="true" @tap="handleMapTap" @markertap="handleMarkerTap" @markerdragend="handleMarkerDrag"
      scale="14">
    </map>

    <!-- 定位按钮 -->
    <image class="location-btn" src="https://lxnapi.ccttiot.com/bike/img/static/uoxanRjBrBrtcYwRGXKa"
      @tap="moveToLocation"></image>

    <!-- 提示文本 -->
    <view class="tip-text" v-if="isDrawing">
      {{ editMode ? '点击锚点进行删除' : '点击地图添加锚点，拖动锚点可调整位置' }}
    </view>

    <!-- 控制按钮组 -->
    <view class="controls">
      <view class="control-btn" @tap="startDrawing" v-if="!isDrawing">开始绘制</view>

      <block v-else>
        <view class="control-btn-group">
          <view class="control-btn control-btn-small" 
            :class="{ 'control-btn-active': !editMode }"
            @tap="toggleEditMode('draw')">绘制锚点</view>

          <view class="control-btn control-btn-small" 
            :class="{ 'control-btn-active': editMode }"
            @tap="toggleEditMode('delete')">删除锚点</view>
        </view>

        <view class="control-btn-group">
          <view class="control-btn" 
            @tap="finishDrawing" 
            :class="{ 'btn-disabled': points.length < 3 }">完成绘制</view>
          <view class="control-btn control-btn-danger" @tap="clearPolygon">清除</view>
        </view>
      </block>
    </view>
  </view>
</template>

<script>
export default {
  name: 'CustomMap',
  props: {
    areaInfo: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      latitude: 39.909,
      longitude: 116.397,
      points: [],
      polygons: [],
      markers: [],
      isDrawing: false,
      editMode: false,
      mapContext: null,
      initialCenter: {
        latitude: 39.909,
        longitude: 116.397
      },
      list: [
        '提示：点击"开始绘制"按钮开始绘制区域',
        '点击地图添加锚点',
        '点击锚点可删除',
        '至少需要3个锚点才能形成有效区域'
      ],
    }
  },
  mounted() {
    this.mapContext = uni.createMapContext('map', this)
  },
  watch: {
    areaInfo: {
      handler(newVal) {
        if (newVal.boundary && newVal.latitude && newVal.longitude) {
          this.initBoundary(newVal)
        }
      },
      immediate: true
    }
  },
  methods: {
    initBoundary(info) {
      this.initialCenter = {
        latitude: info.latitude,
        longitude: info.longitude
      }
      this.latitude = info.latitude
      this.longitude = info.longitude

      const points = info.boundaryStr.split('],[').map(pointStr => {
        const cleanStr = pointStr.replace(/^\[|\]$/g, '')
        const [longitude, latitude] = cleanStr.split(',')

        return {
          longitude: Number(longitude),
          latitude: Number(latitude)
        }
      })

      console.log('解析后的点:', points)

      this.points = points.filter(point =>
        !isNaN(point.latitude) && !isNaN(point.longitude)
      )

      this.updateMarkers()
      this.updatePolygonWithNearestNeighbor()
    },

    updateMarkers() {
      this.markers = this.points.map((point, index) => ({
        id: index,
        latitude: point.latitude,
        longitude: point.longitude,
        width: 20,
        height: 20,
        draggable: true
      }))
    },

    async moveToLocation() {
      try {
        const [err, res] = await uni.getLocation({
          type: 'gcj02'
        });

        if (err) {
          throw new Error('获取位置失败');
        }

        this.latitude = res.latitude;
        this.longitude = res.longitude;

        await new Promise(resolve => setTimeout(resolve, 100));

        this.mapContext.moveToLocation({
          latitude: res.latitude,
          longitude: res.longitude,
          success: () => {
            setTimeout(() => {
              this.mapContext.getScale({
                success: () => { }
              });
            }, 500);
          }
        });
      } catch (error) {
        uni.showToast({
          title: '定位失败,请检查定位权限',
          icon: 'none'
        });
      }
    },

    toggleEditMode(mode) {
      this.editMode = mode === 'delete'
      uni.showToast({
        title: this.editMode ? '请点击锚点进行删除' : '请点击地图添加锚点',
        icon: 'none'
      })
    },

    startDrawing() {
      const currentCenter = {
        latitude: this.latitude,
        longitude: this.longitude
      }

      this.isDrawing = true
      this.editMode = false

      this.$nextTick(() => {
        this.latitude = currentCenter.latitude
        this.longitude = currentCenter.longitude
      })

      uni.showToast({
        title: '开始绘制区域',
        icon: 'none'
      })
    },

    isPointTooClose(point1, point2, threshold = 0.0001) {
      const distance = Math.sqrt(
        Math.pow(point1.latitude - point2.latitude, 2) +
        Math.pow(point1.longitude - point2.longitude, 2)
      )
      return distance < threshold
    },

    cleanNearbyPoints() {
      if (this.points.length < 2) return

      let cleanedPoints = []
      let pointsToKeep = new Set()

      for (let i = 0; i < this.points.length; i++) {
        let shouldKeep = true
        for (let j = 0; j < i; j++) {
          if (pointsToKeep.has(j) && this.isPointTooClose(this.points[i], this.points[j])) {
            shouldKeep = false
            break
          }
        }
        if (shouldKeep) {
          pointsToKeep.add(i)
        }
      }

      pointsToKeep.forEach(index => {
        cleanedPoints.push(this.points[index])
      })

      this.points = cleanedPoints
      this.updateMarkers()
    },

    handleMapTap(e) {
      console.log('handleMapTap', e);
      if (!this.isDrawing || this.editMode) return

      const { latitude, longitude } = e

      const newPoint = { latitude, longitude }
      for (let point of this.points) {
        if (this.isPointTooClose(newPoint, point)) {
          uni.showToast({
            title: '锚点位置过近',
            icon: 'none'
          })
          return
        }
      }

      this.points.push(newPoint)
      this.updateMarkers()

      this.updatePolygonWithNearestNeighbor()
    },

    handleMarkerTap(e) {
      if (!this.editMode) return
      console.log('handleMarkerTap', e);

      const markerId = e.detail.markerId

      if (markerId === undefined || markerId === null) {
        uni.showToast({
          title: '无法删除锚点',
          icon: 'none'
        })
        return
      }

      this.points = this.points.filter((_, index) => index !== markerId)
      this.updateMarkers()

      this.updatePolygonWithNearestNeighbor()
    },

    handleMarkerDrag(e) {
      const { markerId, latitude, longitude } = e.detail

      this.points[markerId] = { latitude, longitude }
      this.updateMarkers()

      this.updatePolygonWithNearestNeighbor()
    },

    updatePolygonWithNearestNeighbor() {
      if (this.points.length < 2) {
        this.polygons = []
        return
      }

      this.cleanNearbyPoints()

      if (this.points.length < 3) {
        this.polygons = [{
          points: [...this.points],
          strokeWidth: 2,
          strokeColor: '#FF0000',
          fillColor: '#FF000050',
          zIndex: 1
        }]
        return
      }

      let centerLat = this.points.reduce((sum, p) => sum + p.latitude, 0) / this.points.length
      let centerLng = this.points.reduce((sum, p) => sum + p.longitude, 0) / this.points.length

      let sortedPoints = [...this.points].sort((a, b) => {
        let angleA = Math.atan2(a.latitude - centerLat, a.longitude - centerLng)
        let angleB = Math.atan2(b.latitude - centerLat, b.longitude - centerLng)
        return angleA - angleB
      })

      sortedPoints.push(sortedPoints[0])

      this.polygons = [{
        points: sortedPoints,
        strokeWidth: 2,
        strokeColor: '#FF0000',
        fillColor: '#FF000050',
        zIndex: 1
      }]
    },

    finishDrawing() {
      if (this.points.length < 3) {
        uni.showToast({
          title: '至少需要3个锚点才能形成区域',
          icon: 'none'
        })
        return
      }

      this.cleanNearbyPoints()

      const centerLat = this.points.reduce((sum, p) => sum + Number(p.latitude), 0) / this.points.length
      const centerLng = this.points.reduce((sum, p) => sum + Number(p.longitude), 0) / this.points.length

      let sortedPoints = [...this.points].sort((a, b) => {
        let angleA = Math.atan2(a.latitude - centerLat, a.longitude - centerLng)
        let angleB = Math.atan2(b.latitude - centerLat, b.longitude - centerLng)
        return angleA - angleB
      })

      const formattedPoints = sortedPoints.map(point => ({
        latitude: Number(Number(point.latitude).toFixed(5)),
        longitude: Number(Number(point.longitude).toFixed(5))
      }))

      this.isDrawing = false
      this.editMode = false

      this.polygons = [{
        points: formattedPoints,
        strokeWidth: 2,
        strokeColor: '#FF0000',
        fillColor: '#FF000050',
        zIndex: 1
      }]

      this.$emit('on-polygon-complete', {
        points: formattedPoints,
        polygon: this.polygons[0]
      })
    },

    clearPolygon() {
      const currentCenter = {
        latitude: this.latitude,
        longitude: this.longitude
      }

      this.points = []
      this.markers = []
      this.polygons = []
      this.isDrawing = false
      this.editMode = false

      this.$nextTick(() => {
        this.latitude = currentCenter.latitude
        this.longitude = currentCenter.longitude
      })

      uni.showToast({
        title: '已清除绘制',
        icon: 'none'
      })
    }
  }
}
</script>

<style>
.map-container {
  width: 100%;
  height: 100vh;
  position: relative;
}

.map {
  width: 100%;
  height: 100%;
}

.location-btn {
  position: fixed;
  right: 30rpx;
  bottom: 300rpx;
  width: 80rpx;
  height: 80rpx;
  z-index: 100;
}

.tip-text {
  position: fixed;
  top: 40rpx;
  left: 50%;
  transform: translateX(-50%);
  background-color: rgba(0, 0, 0, 0.7);
  color: #ffffff;
  padding: 16rpx 30rpx;
  border-radius: 30rpx;
  font-size: 28rpx;
  z-index: 100;
}

.control-btn-group {
  display: flex;
  gap: 20rpx;
  margin-bottom: 20rpx;
}

.control-btn-small {
  min-width: 120rpx;
  height: 60rpx;
  line-height: 60rpx;
  font-size: 24rpx;
  padding: 0 20rpx;
}

.controls {
  position: fixed;
  bottom: 60rpx;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 30rpx;
  z-index: 100;
}

.control-btn {
  pointer-events: auto;
  min-width: 200rpx;
  height: 80rpx;
  line-height: 80rpx;
  background-color: #ffffff;
  border-radius: 10rpx;
  font-size: 28rpx;
  text-align: center;
  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
  margin: 0 10rpx;
  padding: 0 40rpx;
}

.control-btn-danger {
  background-color: #ff4444;
  color: #ffffff;
}

.control-btn-active {
  background-color: #007AFF;
  color: #ffffff;
}

.btn-disabled {
  opacity: 0.5;
  background-color: #cccccc;
  pointer-events: none;
}
</style>