<template>
  <view class="page-container">
    <!-- 顶部状态栏 -->
    <view class="header-section">
      <view class="header-left">
        <text class="device-name">{{ deviceName || '设备名称' }}</text>
        <view class="status-badge" :class="statusClass">{{ statusText }}</view>
      </view>
      <view class="header-right">
        <view class="info-item">
          <text class="info-label">进度</text>
          <text class="info-value">{{ jobProgress}}%</text>
        </view>
        <view class="info-item">
          <text class="info-label">速度</text>
          <text class="info-value">{{ deviceSpeed}}m/s</text>
        </view>
        <view class="info-item">
          <text class="info-label">电量</text>
          <text class="info-value">{{ batteryLevel}}%</text>
        </view>
      </view>
    </view>

    <!-- 地图与控制面板 -->
    <view class="main-content">
      <view class="map-wrapper">
        <view id="mapContainer" class="map-instance"></view>
      </view>
      
      <view class="control-panel">
        <view class="job-info-card">
          <view class="job-info-header">
            <text class="job-info-title">{{ jobInfo.taskName || '作业任务名称' }}</text>
            <text class="job-info-tag">{{ areaTypeText }}</text>
          </view>
          <text class="job-info-time">创建于 {{ formatTime(jobInfo.createTime) }}</text>
        </view>

        <view class="action-buttons-group">
          <button class="action-btn" @click="handleAction('pause')" :disabled="!canPause">暂停作业</button>
          <button class="action-btn" @click="handleAction('stop')" :disabled="!canStop">停止作业</button>
        </view>
        <button class="action-btn recall-btn" @click="handleAction('recall')" :disabled="!canRecall">召回设备</button>
        <button class="action-btn resume-btn" v-if="jobStatus === 3" @click="handleAction('resume')">继续作业</button>
      </view>
    </view>
  </view>
</template>

<script>
import { getInfo, pauseTask, startTask, stopTask, recallTask, getRealtimeData } from '@/api/services/job.js'
import coordinateUtils from '@/utils/coordinateUtils.js'

export default {
  data() {
    return {
      jobId: null,
      deviceId:null,
      jobInfo: {},
      map: null,
      deviceName:'', // 设备名称
      // 地图元素
      areaPolygon: null, // 作业区域
      routePolyline: null, // 规划路线
      passedPolyline: null, // 已走路线
      deviceMarker: null, // 设备图标
      // 状态
      amapLoaded: false,
      pollingTimer: null,
      realtimeTrackPoints: [], // 实时轨迹点：[[lng,lat], ...]
      lastReportTime: null,
      // 模拟数据
      jobProgress: 0,
      deviceSpeed: 0.0,
      batteryLevel: 0,
      // 字典
      statusMap: {
        0: '未开始',
        1: '进行中',
        2: '已完成',
        3: '已暂停',
        4: '已停止',
        5: '已取消',
        default: '未知'
      },
      areaTypeMap: {
        1: '回字形',
        2: '弓字形',
        3: '自定义',
        4: '垄沟',
        default: '未知区域'
      }
    }
  },
  computed: {
    jobStatus() {
      return this.jobInfo.taskStatus
    },
    statusText() {
      return this.statusMap[this.jobStatus] || this.statusMap.default
    },
    statusClass() {
      return `status-${this.jobStatus}`
    },
    areaTypeText() {
      return this.areaTypeMap[this.jobInfo.workAreas && this.jobInfo.workAreas.areaType || 0] || this.areaTypeMap.default
    },
    // 按钮可用状态
    canPause() {
      return this.jobStatus === 1
    },
    canResume() {
      return this.jobStatus === 3
    },
    canStop() {
      return [0, 1, 3].includes(this.jobStatus)
    },
    canRecall() {
      return [0, 1, 3].includes(this.jobStatus)
    }
  },
  onLoad(options) {
    if (options.id || options.deviceId) {
      this.jobId = options.id
      this.deviceId = options.deviceId
      this.deviceName = options.deviceName
      this.loadJobDetails()
    } else {
      uni.showToast({ title: '缺少作业ID', icon: 'none' })
      uni.navigateBack()
    }
  },
  onReady() {
    this.initMap()
  },
  onUnload() {
    this.clearPolling()
  },
  methods: {
    // 加载作业详情
    async loadJobDetails() {
      uni.showLoading({ title: '加载中...' })
      try {
        const res = await getInfo(this.jobId)
        if (res.data.code === 200 &&res.data.data.workAreas) {
          this.jobInfo = res.data.data || {}
          // 更新模拟数据
          // this.jobProgress = this.jobInfo.progress || 0
          // this.deviceSpeed = this.jobInfo.speed || 0.0
          // this.batteryLevel = this.jobInfo.battery || 0
          
          this.updateMapElements()
          this.setupPolling()
        } else {
          throw new Error(res.data.msg || '加载失败')
        }
      } catch (err) {
        uni.showToast({ title: err.message, icon: 'none' })
      } finally {
        uni.hideLoading()
      }
    },
    // 初始化地图
    initMap() {
      if (window.AMap) {
        this.createMap()
      } else {
        const script = document.createElement('script')
        script.src = `https://webapi.amap.com/maps?v=2.0&key=9f2cac7ea18905dd3830cf7360a43a35`
        script.onload = this.createMap
        document.head.appendChild(script)
      }
    },
    createMap() {
      this.map = new AMap.Map('mapContainer', {
        zoom: 16,
        viewMode: '2D',
        pitch: 45
      })
      this.map.add(new AMap.TileLayer.Satellite())
      // ToolBar 在 v2 需要通过 plugin 异步加载；直接 new AMap.ToolBar() 会报：AMap.ToolBar is not a constructor
      try {
        AMap.plugin(['AMap.ToolBar'], () => {
          try {
            const toolBar = new AMap.ToolBar()
            this.map.addControl(toolBar)
          } catch (e) {
            // eslint-disable-next-line no-console
            console.warn('[job-detail] init toolbar failed', e)
          }
        })
      } catch (e) {
        // eslint-disable-next-line no-console
        console.warn('[job-detail] AMap.plugin ToolBar failed', e)
      }

      this.amapLoaded = true
      // 地图准备好后，如果作业信息已加载，则渲染一次静态元素 & 启动轮询
      if (this.jobInfo && Object.keys(this.jobInfo).length) {
        this.updateMapElements()
        this.setupPolling()
      }
    },
    // 更新地图元素
    updateMapElements() {
      
      // 你当前接口返回：jobInfo.workAreas.waypoints 直接就是点数组：[{lng,lat}, ...]
      // 同时兼容未来可能的结构：
      // - workAreas 是数组：[{ waypoints:[...] }, ...]
      // - workAreas 是对象：{ waypoints:[...] }
      if (!this.amapLoaded) return

      const workAreas = this.jobInfo && this.jobInfo.workAreas
      let points = []

      // 情况A：workAreas.waypoints = [{lng,lat}, ...]（你现在的情况）
      // 注意：waypoints 有可能被后端返回成字符串 / 对象（单点）/ null，先做数组兜底
      if (workAreas && workAreas.waypoints) {
        try {
          // 如果是字符串，尝试解析为 JSON
          points = typeof workAreas.waypoints === 'string' 
            ? JSON.parse(workAreas.waypoints)
            : workAreas.waypoints;
          
          // 确保解析后是数组
          if (!Array.isArray(points)) {
            console.warn('[job-detail] workAreas.waypoints is not an array after parsing:', workAreas.waypoints);
            points = [];
          }
        } catch (e) {
          console.error('[job-detail] Failed to parse workAreas.waypoints:', e);
          points = [];
        }
    }


      if (!points.length) return
      console.log("points",points);

      const waypoints = points
        .filter(p => p && p.lng != null && p.lat != null)
        .map(p => [p.lng, p.lat])

        console.log("waypoints",waypoints);
        
      if (waypoints.length <= 2) return

      // 1. 绘制作业区域
      if (!this.areaPolygon) {
        this.areaPolygon = new AMap.Polygon({
          map: this.map,
          path: waypoints,
          strokeColor: '#28F',
          strokeWeight: 2,
          fillColor: '#28F',
          fillOpacity: 0.1
        })
      } else {
        this.areaPolygon.setPath(waypoints)
      }

      // 2. 绘制规划路线
      // 注意：AMap.Polyline 的 path 需要是 [[lng,lat], ...] 或 AMap.LngLat[]。
      // 这里统一把 routePoints 归一化成 [[lng,lat], ...]，避免出现 undefined[0] 这类错误。
      const rawRoutePoints = this.jobInfo.routePoints || []

      let routePath = []
      if (Array.isArray(rawRoutePoints) && rawRoutePoints.length) {
        // 可能是 [{lng,lat},...] 或 [[lng,lat],...]
        const first = rawRoutePoints[0]
        if (Array.isArray(first)) {
          routePath = rawRoutePoints
        } else {
          routePath = rawRoutePoints
            .filter(p => p && p.lng != null && p.lat != null)
            .map(p => [p.lng, p.lat])
        }
      } else {
        // 没有 routePoints 就用区域边界 waypoints（它已经是 [[lng,lat],...]）
        routePath = waypoints
      }

      if (routePath.length >= 2) {
        if (!this.routePolyline) {
          this.routePolyline = new AMap.Polyline({
            map: this.map,
            path: routePath,
            showDir: true,
            strokeColor: '#28F',
            strokeWeight: 6
          })
        } else {
          this.routePolyline.setPath(routePath)
        }
      }

      // 3. 绘制已走轨迹 (假设后端返回 passedPoints)
      const rawPassedPoints = this.jobInfo.passedPoints || []

      let passedPath = []
      if (Array.isArray(rawPassedPoints) && rawPassedPoints.length) {
        const first = rawPassedPoints[0]
        if (Array.isArray(first)) {
          passedPath = rawPassedPoints
        } else {
          passedPath = rawPassedPoints
            .filter(p => p && p.lng != null && p.lat != null)
            .map(p => [p.lng, p.lat])
        }
      }

      // 3. 绘制已走轨迹：优先用实时轮询轨迹；否则使用后端历史 passedPoints
      const finalPassedPath = (this.realtimeTrackPoints && this.realtimeTrackPoints.length)
        ? this.realtimeTrackPoints
        : passedPath

      if (!this.passedPolyline) {
        this.passedPolyline = new AMap.Polyline({
          map: this.map,
          strokeColor: '#AF5',
          strokeWeight: 6
        })
      }
      this.passedPolyline.setPath(finalPassedPath)

      // 4. 绘制设备位置
      const devicePosition = this.jobInfo.currentPosition
      
      if (devicePosition && devicePosition.lng) {
        if (!this.deviceMarker) {
          this.deviceMarker = new AMap.Marker({ map: this.map, position: [devicePosition.lng, devicePosition.lat]})
        } else {
          this.deviceMarker.setPosition([devicePosition.lng, devicePosition.lat])
        }
        this.map.setCenter([devicePosition.lng, devicePosition.lat])
      }

      // 首次渲染静态元素时再 fitView，实时更新时不要频繁 fitView
      this.map.setFitView()
    },
    // 设置轮询（实时位置 + 轨迹）
    setupPolling() {
      // 先清一次，避免重复创建 interval
      this.clearPolling()

      // 没有 deviceId 就无法拉实时数据
      const deviceId = this.deviceId
      if (!deviceId) return

      // 仅在进行中/暂停时轮询（你也可以放开为所有状态）
      if (![1, 3].includes(this.jobStatus)) return

      // 立刻拉一次，避免要等第一轮 interval
      this.fetchRealtimeAndUpdate()

      // 3 秒轮询一次
      this.pollingTimer = setInterval(() => {
        this.fetchRealtimeAndUpdate()
      }, 3000)
    },

    clearPolling() {
      if (this.pollingTimer) {
        clearInterval(this.pollingTimer)
        this.pollingTimer = null
      }
    },

    async fetchRealtimeAndUpdate() {
      try {
        console.log("this.jobInfo",this.jobInfo);
        
        const deviceId =this.deviceId
        if (!deviceId) return

        const res = await getRealtimeData(deviceId)
        const payload = res && res.data && (res.data.data || res.data)

        if (!payload) return

        // 检查作业状态，如果已完成则提示并退出
        if (payload.state === 3 || payload.state === 'FINISHED' ) {
          this.clearPolling()
          uni.showModal({
            title: '提示',
            content: '当前作业已完成，是否退出当前页面',
            success: (modalRes) => {
              if (modalRes.confirm) {
                uni.navigateBack()
              }
            }
          })
          return
        }

        // 可选：丢弃时间倒退的数据
        const reportTime = payload.reportTime
        if (reportTime && this.lastReportTime && reportTime < this.lastReportTime) {
          return
        }
        if (reportTime) this.lastReportTime = reportTime

        // 更新头部信息（如果接口有）
        if (payload.progress != null) this.jobProgress = payload.progress
        if (payload.speed != null) this.deviceSpeed = payload.speed
        if (payload.battery != null) this.batteryLevel = payload.battery

        const pt = payload.currentPoint
        if (!pt || pt.x == null || pt.y == null) return

        // currentPoint: {x,y} 这里按接口文档理解为 (lng,lat)
        const lngLat = [pt.x, pt.y]
        
        // 获取行驶方向
        const direction = payload.direction || 0

        this.updateDeviceMarker(lngLat, direction)
        this.appendTrackPoint(lngLat)
        this.updatePassedPolyline()
      } catch (e) {
        // eslint-disable-next-line no-console
        console.warn('[job-detail] fetchRealtimeAndUpdate failed', e)
      }
    },

    updateDeviceMarker(lngLat, direction = 0) {
      if (!this.amapLoaded || !this.map) return
      if (!lngLat || lngLat.length !== 2) return
      
      // 创建一个 Icon
      var startIcon = new AMap.Icon({
          // 图标尺寸
          size: new AMap.Size(45, 45),
          // 图标的取图地址
          image: '/static/icons/gecaoji.png',
          // 图标所用图片大小
          imageSize: new AMap.Size(45, 45),
          // 图标取图偏移量
          // imageOffset: new AMap.Pixel(-9, -3)
      });
      
      if (!this.deviceMarker) {
        this.deviceMarker = new AMap.Marker({
          map: this.map,
          position: lngLat,
          icon: startIcon,
          anchor: 'center', // 设置锚点为中心，使图标居中显示在路线上
          angle: direction // 设置初始旋转角度
        })
      } else {
        this.deviceMarker.setPosition(lngLat)
        this.deviceMarker.setAngle(direction) // 更新旋转角度
      }

      // 轻量跟随：中心跟随但不 fitView，避免每次抖动缩放
      this.map.setCenter(lngLat)
    },

    appendTrackPoint(lngLat) {
      if (!lngLat || lngLat.length !== 2) return

      const last = this.realtimeTrackPoints.length
        ? this.realtimeTrackPoints[this.realtimeTrackPoints.length - 1]
        : null

      // 去重：相同点不追加
      if (last && last[0] === lngLat[0] && last[1] === lngLat[1]) return

      this.realtimeTrackPoints.push(lngLat)
    },

    updatePassedPolyline() {
      if (!this.amapLoaded || !this.map) return

      // 至少两个点才画线
      if (!this.realtimeTrackPoints || this.realtimeTrackPoints.length < 2) return

      if (!this.passedPolyline) {
        this.passedPolyline = new AMap.Polyline({
          map: this.map,
          path: this.realtimeTrackPoints,
          strokeColor: '#AF5',
          strokeWeight: 6
        })
      } else {
        this.passedPolyline.setPath(this.realtimeTrackPoints)
      }
    },
    // 处理按钮操作
    async handleAction(action) {
      const actions = {
        pause: { api: pauseTask, msg: '作业已暂停' },
        resume: { api: startTask, msg: '作业已继续' },
        stop: { api: stopTask, msg: '作业已停止' },
        recall: { api: recallTask, msg: '召回指令已发送' }
      }
      const currentAction = actions[action]

      if (action === 'stop') {
        uni.showModal({
          title: '确认停止',
          content: '停止后无法恢复，确定吗？',
          success: res => res.confirm && this.executeAction(currentAction)
        })
      } else {
        this.executeAction(currentAction)
      }
    },
    async executeAction({ api, msg }) {
      try {
        const res = await api(this.jobId)
        if (res.data.code === 200) {
          uni.showToast({ title: msg, icon: 'success' })
          this.loadJobDetails()
        } else {
          throw new Error(res.data.msg || '操作失败')
        }
      } catch (err) {
        uni.showToast({ title: err.message, icon: 'none' })
      }
    },
    // 格式化时间
    formatTime(timeStr) {
      if (!timeStr) return '--'
      return timeStr.substring(0, 16)
    }
  }
}
</script>

<style scoped>
.page-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: #f4f6f8;
}

.header-section {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20rpx 30rpx;
  background-color: #ffffff;
  box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.05);
}

.header-left {
  display: flex;
  align-items: center;
}

.device-name {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
  margin-right: 16rpx;
}

.status-badge {
  font-size: 22rpx;
  padding: 4rpx 12rpx;
  border-radius: 16rpx;
  color: #fff;
}
.status-0 { background-color: #1890ff; } /* 未开始 */
.status-1 { background-color: #52c41a; } /* 进行中 */
.status-2 { background-color: #8c8c8c; } /* 已完成 */
.status-3 { background-color: #fa8c16; } /* 已暂停 */
.status-4 { background-color: #f5222d; } /* 已停止 */
.status-5 { background-color: #bfbfbf; } /* 已取消 */

.header-right {
  display: flex;
  /**gap: 24rpx; **/
}

.info-item {
  display: flex;
  align-items: baseline;
  font-size: 24rpx;
  padding-left: 10rpx;
}

.info-label {
  color: #888;
  margin-right: 8rpx;
}

.info-value {
  font-size: 24rpx;
  font-weight: 600;
  color: #333;
}

.main-content {
  flex: 1;
  position: relative;
}

.map-wrapper, .map-instance {
  width: 100%;
  height: 100%;
}

.control-panel {
  position: absolute;
  bottom: 30rpx;
  right: 20rpx;
  width: 320rpx;
  background-color: rgba(255, 255, 255, 0.9);
  border-radius: 20rpx;
  padding: 24rpx;
  box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.1);
  backdrop-filter: blur(10px);
}

.job-info-card {
  margin-bottom: 20rpx;
}

.job-info-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 8rpx;
}

.job-info-title {
  font-size: 28rpx;
  font-weight: 600;
  color: #333;
  flex: 1;
}

.job-info-tag {
  font-size: 20rpx;
  background-color: #e6f7ff;
  color: #1890ff;
  padding: 2rpx 8rpx;
  border-radius: 6rpx;
  margin-left: 10rpx;
}

.job-info-time {
  font-size: 22rpx;
  color: #888;
}

.action-buttons-group {
  display: flex;
  gap: 16rpx;
  margin-bottom: 16rpx;
}

.action-btn {
  flex: 1;
  font-size: 24rpx;
  padding: 12rpx 0;
  margin: 0;
  border-radius: 10rpx;
  background-color: #1890ff;
  color: #fff;
}

.action-btn:disabled {
  background-color: #d9d9d9;
  color: #8c8c8c;
}

.recall-btn {
  width: 100%;
  background-color: #faad14;
  margin-bottom: 16rpx;
}

.resume-btn {
  width: 100%;
  background-color: #52c41a;
}
</style>

