<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 setup>
import { ref, computed } from 'vue'
import { getInfo, pauseTask, startTask, stopTask, recallTask, getRealtimeData } from '@/api/services/job.js'

// Props from route params (will be set in onLoad)
const jobId = ref(null)
const deviceId = ref(null)
const deviceName = ref('') // 设备名称
const jobInfo = ref({})

// 地图相关
const map = ref(null)
const areaPolygon = ref(null) // 作业区域
const routePolyline = ref(null) // 规划路线
const passedPolyline = ref(null) // 已走路线
const deviceMarker = ref(null) // 设备图标

// 状态
const amapLoaded = ref(false)
const pollingTimer = ref(null)
const realtimeTrackPoints = ref([]) // 实时轨迹点：[[lng,lat], ...]
const lastReportTime = ref(null)

// 模拟数据
const jobProgress = ref(0)
const deviceSpeed = ref(0.0)
const batteryLevel = ref(0)

// 字典
const statusMap = {
  0: '未开始',
  1: '进行中',
  2: '已完成',
  3: '已暂停',
  4: '已停止',
  5: '已取消',
  default: '未知'
}

const areaTypeMap = {
  1: '回字形',
  2: '弓字形',
  3: '自定义',
  4: '垄沟',
  default: '未知区域'
}

// Computed properties
const jobStatus = computed(() => jobInfo.value.taskStatus)
const statusText = computed(() => statusMap[jobStatus.value] || statusMap.default)
const statusClass = computed(() => `status-${jobStatus.value}`)
const areaTypeText = computed(() => {
  const areaType = jobInfo.value.workAreas && jobInfo.value.workAreas.areaType || 0
  return areaTypeMap[areaType] || areaTypeMap.default
})

// 按钮可用状态
const canPause = computed(() => jobStatus.value === 1)
const canResume = computed(() => jobStatus.value === 3)
const canStop = computed(() => [0, 1, 3].includes(jobStatus.value))
const canRecall = computed(() => [0, 1, 3].includes(jobStatus.value))

// Lifecycle hooks
const onLoad = (options) => {
  if (options.id || options.deviceId) {
    jobId.value = options.id
    deviceId.value = options.deviceId
    deviceName.value = options.deviceName
    loadJobDetails()
  } else {
    uni.showToast({ title: '缺少作业ID', icon: 'none' })
    uni.navigateBack()
  }
}

const onReady = () => {
  initMap()
}

const onUnload = () => {
  clearPolling()
}

// Methods
const loadJobDetails = async () => {
  uni.showLoading({ title: '加载中...' })
  try {
    const res = await getInfo(jobId.value)
    if (res.data.code === 200 &&res.data.data.workAreas) {
      jobInfo.value = res.data.data || {}
      
      updateMapElements()
      setupPolling()
    } else {
      throw new Error(res.data.msg || '加载失败')
    }
  } catch (err) {
    uni.showToast({ title: err.message, icon: 'none' })
  } finally {
    uni.hideLoading()
  }
}

const initMap = () => {
	// #ifdef H5
  if (window.AMap) {
    createMap()
  } else {
    const script = document.createElement('script')
    script.src = `https://webapi.amap.com/maps?v=2.0&key=9f2cac7ea18905dd3830cf7360a43a35`
    script.onload = createMap
    document.head.appendChild(script)
  }
	// #endif
	// #ifndef H5
	// 非 H5 平台使用 uni-app 地图组件
	console.warn('当前平台不支持动态加载高德地图脚本，请使用 uni-app 地图组件')
	// #endif
}

const createMap = () => {
  map.value = new AMap.Map('mapContainer', {
    zoom: 16,
    viewMode: '2D',
    pitch: 45
  })
  map.value.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()
        map.value.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)
  }

  amapLoaded.value = true
  // 地图准备好后，如果作业信息已加载，则渲染一次静态元素 & 启动轮询
  if (jobInfo.value && Object.keys(jobInfo.value).length) {
    updateMapElements()
    setupPolling()
  }
}

const updateMapElements = () => {
  
  // 你当前接口返回：jobInfo.workAreas.waypoints 直接就是点数组：[{lng,lat}, ...]
  // 同时兼容未来可能的结构：
  // - workAreas 是数组：[{ waypoints:[...] }, ...]
  // - workAreas 是对象：{ waypoints:[...] }
  if (!amapLoaded.value) return

  const workAreas = jobInfo.value && jobInfo.value.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 (!areaPolygon.value) {
    areaPolygon.value = new AMap.Polygon({
      map: map.value,
      path: waypoints,
      strokeColor: '#28F',
      strokeWeight: 2,
      fillColor: '#28F',
      fillOpacity: 0.1
    })
  } else {
    areaPolygon.value.setPath(waypoints)
  }

  // 2. 绘制规划路线
  // 注意：AMap.Polyline 的 path 需要是 [[lng,lat], ...] 或 AMap.LngLat[]。
  // 这里统一把 routePoints 归一化成 [[lng,lat], ...]，避免出现 undefined[0] 这类错误。
  const rawRoutePoints = jobInfo.value.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 (!routePolyline.value) {
      routePolyline.value = new AMap.Polyline({
        map: map.value,
        path: routePath,
        showDir: true,
        strokeColor: '#28F',
        strokeWeight: 6
      })
    } else {
      routePolyline.value.setPath(routePath)
    }
  }

  // 3. 绘制已走轨迹 (假设后端返回 passedPoints)
  const rawPassedPoints = jobInfo.value.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 = (realtimeTrackPoints.value && realtimeTrackPoints.value.length)
    ? realtimeTrackPoints.value
    : passedPath

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

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

  // 首次渲染静态元素时再 fitView，实时更新时不要频繁 fitView
  map.value.setFitView()
}

const setupPolling = () => {
  // 先清一次，避免重复创建 interval
  clearPolling()

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

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

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

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

const clearPolling = () => {
  if (pollingTimer.value) {
    clearInterval(pollingTimer.value)
    pollingTimer.value = null
  }
}

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

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

    if (!payload) return

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

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

    // 更新头部信息（如果接口有）
    if (payload.progress != null) jobProgress.value = payload.progress
    if (payload.speed != null) deviceSpeed.value = payload.speed
    if (payload.battery != null) batteryLevel.value = 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

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

const updateDeviceMarker = (lngLat, direction = 0) => {
  if (!amapLoaded.value || !map.value) 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 (!deviceMarker.value) {
    deviceMarker.value = new AMap.Marker({
      map: map.value,
      position: lngLat,
      icon: startIcon,
      anchor: 'center', // 设置锚点为中心，使图标居中显示在路线上
      angle: direction // 设置初始旋转角度
    })
  } else {
    deviceMarker.value.setPosition(lngLat)
    deviceMarker.value.setAngle(direction) // 更新旋转角度
  }

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

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

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

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

  realtimeTrackPoints.value.push(lngLat)
}

const updatePassedPolyline = () => {
  if (!amapLoaded.value || !map.value) return

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

  if (!passedPolyline.value) {
    passedPolyline.value = new AMap.Polyline({
      map: map.value,
      path: realtimeTrackPoints.value,
      strokeColor: '#AF5',
      strokeWeight: 6
    })
  } else {
    passedPolyline.value.setPath(realtimeTrackPoints.value)
  }
}

const handleAction = async (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 && executeAction(currentAction)
    })
  } else {
    executeAction(currentAction)
  }
}

const executeAction = async ({ api, msg }) => {
  try {
    const res = await api(jobId.value)
    if (res.data.code === 200) {
      uni.showToast({ title: msg, icon: 'success' })
      loadJobDetails()
    } else {
      throw new Error(res.data.msg || '操作失败')
    }
  } catch (err) {
    uni.showToast({ title: err.message, icon: 'none' })
  }
}

const 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>
