<template>
  <view class="location-box">
    <!-- 地图 -->
    <view class="map">
      <map
        id="myMap"
        ref="mapRef"
        class="map-box"
        scale="14"
        :latitude="latitud.latitude"
        :longitude="latitud.longitude"
        :markers="markers"
        :circles="circles"
        show-location
        show-compass
      >
      </map>
    </view>
    <!-- 打卡 -->
    <view class="box-cont">
      <view class="visit-operate">
        <view class="title"> <text>选择拜访对象</text></view>
        <view class="visit-box">
          <picker-view indicator-class="select" class="visit-list" @change="visitScroll">
            <picker-view-column>
              <view
                class="info-row"
                v-for="(item, index) in locationList"
                :key="index"
                :class="{ act: act === index }"
              >
                <view> {{ item.signEntName }} （{{ item.dis }} ）</view>
              </view>
            </picker-view-column>
          </picker-view>
          <!-- 打卡 -->
          <view class="sign-box">
            <view class="sign-in" @click="signFn" v-if="notClockedIn">
              <view>签到</view>
            </view>
            <view class="sign-in" @click="toDetail" v-else>
              <view>签退</view>
            </view>
          </view>
        </view>
        <view class="check-in-time" v-if="!notClockedIn">
          <view>签到时间: {{ signResultTime }}</view>
        </view>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import dayjs from 'dayjs'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { getCurrentInstance, ref, reactive, onUnmounted } from 'vue'
import { getWxLocationApi } from '@/wxUtils/index'
import { debounce } from '@/utils/index'
import { useTask } from '@/store/task'
import {
  getDictPointApi,
  getPointSignInfoApi,
  signTempApi,
  getSignTempResultApi
} from '@/service/modules/getTask'
import { getDistance } from '@/utils/index'
const useTaskStore = useTask()

const { ctx }: any = getCurrentInstance()

const mapRef = ref()

const latitud = reactive({
  latitude: 39.909,
  longitude: 116.39742
})
const markers = ref<any[]>([])
const circles = ref<any[]>([])
const myMap = ref()

const taskTypeId = ref('')
const title = ref('')
// 定时器
const timer = ref()
onLoad(async (e: any) => {
  // 保存当前任务类型和标题
  title.value = e?.title
  taskTypeId.value = e?.value

  myMap.value = uni.createMapContext('myMap', ctx)
  // 获取可打卡范围
  await getDictPoint()
})

const getLocation = async () => {
  try {
    // 获取位置
    const res: any = await getWxLocationApi()
    const { latitude, longitude } = res || {}

    // 当本次坐标与上次坐标不相同时
    if (latitud.latitude !== latitude || latitud.longitude !== longitude) {
      latitud.latitude = latitude
      latitud.longitude = longitude
      flag.value = true
      setMapRegion() // 设置地图区域

      // 获取医院列表
      await fetchHospitalList()
    }
  } catch (err) {
    handleLocationError()
  }
}

// 提取获取医院列表的函数
const fetchHospitalList = async () => {
  try {
    await getPointSignInfo()
  } catch (err) {
    console.error('获取终端失败，请联系管理员')
  }
}

// 错误处理函数
const handleLocationError = () => {
  flag.value = false
  // 清除定时器
  if (timer.value) {
    clearInterval(timer.value)
    timer.value = null
  }

  uni.showModal({
    title: '错误提示',
    showCancel: false,
    content: '获取定位失败'
  })
}

const mapRadius = ref()
const getDictPoint = async () => {
  uni.showLoading()
  const res = await getDictPointApi()
  mapRadius.value = res.data[0].value
  uni.hideLoading()
}
// 设置地图范围
const setMapRegion = () => {
  myMap.value.getRegion({
    success() {
      // 获取东经西经维度
      circles.value.push({
        latitude: latitud.latitude,
        longitude: latitud.longitude,
        color: '#ffffff',
        fillColor: '#7cb5ec88',
        radius: Number(mapRadius.value),
        strokeWidth: 2
      })
    }
  })
}

const hospitalList = ref<any[]>([])
const getPointSignInfo = async () => {
  const res = await getPointSignInfoApi(latitud)
  hospitalList.value = res.data
  calcDistance()
}

const curentDistance = ref()
// 计算当前地址和医院的距离，得到最短的距离
async function calcDistance() {
  //! 数据处理
  if (!hospitalList.value.length) return
  let hospitalMap = hospitalList.value.map((item: any) => {
    // 计算每个地点与当前位置的距离
    item.distance = getDistance(
      latitud.longitude,
      latitud.latitude,
      item!.longitude,
      item!.latitude
    )
    return item
  })
  // 根据距离排序
  hospitalMap.sort((itemA: any, itemB: any) => {
    return itemA.distance - itemB.distance > 0 ? 1 : -1
  })
  hospitalList.value = hospitalMap
  // 默认设置最近的地点
  curentDistance.value = hospitalMap[0]
  // 获取第一个医院的签到结果
  getsignTempResult()
  setMarkers(curentDistance.value)
  checkSignInState()
}
//  设置marker
const setMarkers = (distanceItem: any) => {
  markers.value = [
    {
      id: Number(distanceItem.signEntId),
      latitude: distanceItem.latitude,
      longitude: distanceItem.longitude,
      width: 25,
      height: 35,
      callout: {
        display: 'BYCLICK',
        content: distanceItem.signEntName,
        color: 'black',
        borderRadius: 8,
        bgColor: '#ffffff',
        padding: 10,
        textAlign: 'center'
      }
    }
  ]
}

// 是否在范围内
const withinTheScopeOf = ref(false)
const locationList = ref<any[]>([])
// 检查可以签到状态
const checkSignInState = () => {
  // 计算当前距离距离选择地点的距离
  let result = getDistance(
    latitud.longitude,
    latitud.latitude,
    curentDistance?.value?.longitude,
    curentDistance?.value?.latitude
  )
  result = result * 1000
  // 半径范围与距离判断
  withinTheScopeOf.value = mapRadius.value >= result
  // 对地点进行过滤,去除超过当前半径范围内的
  locationList.value = hospitalList.value.filter((item) => {
    let itemResult = getDistance(latitud.longitude, latitud.latitude, item.longitude, item.latitude)
    itemResult = itemResult * 1000
    if (mapRadius.value > itemResult) {
      item.value = item.signEntId
      item.label = item.signEntName
      return item
    }
  })
}

const act = ref(0)

const getResult = ref(false)
// 拜访对象滚动
const visitScroll = async (event: any) => {
  getResult.value = true
  uni.showLoading({
    mask: true,
    title: '获取签到信息中'
  })
  let curr = event.detail.value[0]
  act.value = curr
  // 设置当前选中的地方,重置markers
  curentDistance.value = locationList.value[curr]

  await getSignInfo()
  setMarkers(curentDistance.value)
  uni.hideLoading()
}

const getSignInfo = debounce(() => {
  getsignTempResult()
}, 500)

const getsignTempResult = async () => {
  uni.showLoading({
    mask: true,
    title: '获取签到信息中'
  })
  const obj = {
    locationId: curentDistance.value?.signEntId,
    taskTypeId: taskTypeId.value,
    combine: true,
    signTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
  }
  const res = await getSignTempResultApi(obj)
  if (res.data) {
    notClockedIn.value = false
    signResultTime.value = res.data
  } else {
    notClockedIn.value = true
    signResultTime.value = ''
  }
  getResult.value = false
  uni.hideLoading()
}

const notClockedIn = ref(true)
const signResultTime = ref('')
const signFn = async () => {
  if (!curentDistance.value) {
    return uni.showToast({
      title: '请选择签到地点',
      icon: 'none'
    })
  }
  const obj = {
    locationId: curentDistance.value?.signEntId,
    taskTypeId: taskTypeId.value,
    combine: true,
    signTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
  }
  const res = await signTempApi(obj)
  if (res.code === 0) {
    uni.showToast({
      title: '签到成功',
      icon: 'none'
    })
    notClockedIn.value = false
    signResultTime.value = res.data
  }
}

let flag = ref(false)
onShow(async () => {
  Lock.value = false
  //  获取当前坐标 并且每分钟更新一次当前坐标
  await getLocation()

  // 仅当获取定位成功后才启动定时器
  if (flag.value) {
    timer.value = setInterval(() => {
      getLocation()
    }, 60 * 1000)
  }
})

const Lock = ref(false)
// 签退去填写表单

const toDetail = debounce(() => {
  setTimeout(() => {
    if (getResult.value) return

    uni.showLoading({
      mask: true,
      title: '加载中'
    })

    let TIME: number = 10
    // 签退时间

    const signOutTime = dayjs(signResultTime.value)

    // 获取当前时间
    const currentTime = dayjs()

    // 计算时间差是否超过15分钟

    if (currentTime.diff(signOutTime, 'minute') > TIME) {
      const data = {
        address: curentDistance.value?.signEntName,
        locationId: curentDistance.value?.signEntId,
        signTime: signResultTime.value,
        signEntType: curentDistance.value?.signEntType,
        longitude: curentDistance.value?.longitude,
        latitude: curentDistance.value?.latitude,
        checkOutTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
      }

      useTaskStore.setSignAddressInfo(data)
      uni.navigateTo({
        url: `/pages-sub-task/task/index?value=${taskTypeId.value}&title=${title.value}`
      })
      uni.hideLoading()
      setTimeout(() => {
        Lock.value = false
      }, 3000)
    } else {
      uni.showToast({
        title: `签到和签退时间间隔不可少于${TIME}分钟。`,
        icon: 'none'
      })
    }
  }, 1000)
}, 500)

// 卸载
onUnmounted(() => {
  if (timer.value) {
    clearInterval(timer.value)
  }
})
</script>

<style lang="scss" scoped>
.location-box {
  height: 100vh;
  display: flex;
  flex-direction: column;
  .map {
    height: 450rpx;
    .map-box {
      width: 100%;
      height: 470rpx;
      position: relative;
    }
  }
  .box-cont {
    flex: 1;
    background-color: #fff;
    position: relative;
    z-index: 99;
    padding: 30rpx;
    border-radius: 16px;
    .visit-operate {
      .title {
        font-size: 28rpx;
        color: #333;
        font-weight: 600;
        line-height: 40rpx;
      }
      .visit-box {
        flex: 1;
        margin-top: 40rpx;
        .visit-list {
          height: 350rpx;
        }
        .info-row {
          height: 45rpx;
          line-height: 60rpx;
          text-align: center;
        }
        .sign-box {
          margin-top: 30rpx;
          display: flex;
          align-items: center;
          justify-content: center;
          .sign-in {
            width: 160rpx;
            height: 160rpx;
            border-radius: 50%;
            background-color: #6eb657;
            text-align: center;
            line-height: 160rpx;
            font-size: 36rpx;
            color: #fff;
            font-weight: 600;
          }
        }
      }
      .check-in-time {
        margin-top: 60rpx;
        text-align: center;
        font-size: 30rpx;
        color: #000;
      }
    }
  }
}
</style>
