<template>
  <div>
    <CardContainer>
      <div>
        <el-button v-if="isShowDuty" type="primary" style="display: block;margin: auto auto 20px;" @click="startDuty">开始值班</el-button>
        <div style="display: flex;">
          <button class="sign-btn" v-if="signStatus === 1" @click="singType=1,clockIn(false)">
            <span>上班打卡</span>
          </button>
          <button class="sign-btn" v-if="signStatus === 2 || signStatus === 0" @click="singType=1,clockIn(true)">
            <span>上班外勤打卡</span>
          </button>

          <template v-if="todayAttendance.sign_in_at">
            <button class="sign-btn" v-if="signStatus === 1" @click="singType=2,clockIn(false)">
              <span>下班打卡</span>
            </button>
            <button class="sign-btn" v-if="signStatus === 2 || signStatus === 0" @click="singType=2,clockIn(true)">
              <span>下班外勤打卡</span>
            </button>
          </template>
        </div>
        <div class="sign-info">
          <div class="sign-statue">
            <div>打卡状态 <el-tag size="small" effect="dark" type="primary">{{ (isGetLocation || isIpSign) ? (isOutSign ? '外勤打卡' : '可打卡') : '不可打卡' }}</el-tag></div>
            <div v-if="!isIpSign">当前位置： <span v-if="isGetLocation">
            <el-tag size="small" type="primary" effect="dark">{{pos.address}}</el-tag>
            （{{pos.lng}},{{pos.lat}}）</span></div>
            <div v-if="isIpSign">
              <el-tag size="small" type="primary" effect="dark">ip打卡</el-tag>
            </div>
            <div v-if="!isIpSign">
              <div>当前距离：{{ nowDistance }}千米</div>
              <div>最大打卡范围：{{ maxDistance }}千米</div>
            </div>
          </div>

          <div class="sign-log" v-if="todayAttendance.details && todayAttendance.details.length > 0">
            <el-timeline>
              <el-timeline-item
                v-for="(item) in todayAttendance.details"
                :key="item.id"
                :type="item.sign_at_image ? 'warning' : 'primary'"
                :timestamp="item.sign_at">
                {{ item.sign_at_address }}{{ item.sign_at_image ? '(外勤)' : '' }}
              </el-timeline-item>
            </el-timeline>
          </div>
        </div>
      </div>

      <MonthStatics ref="MonthStatics" @today-attendance="e => todayAttendance = e"></MonthStatics>
    </CardContainer>

    <vxe-modal
      v-model="isShow"
      show-footer
      :z-index="zIndex"
      title="外勤打卡"
      show-confirm-button
      :width="defaultModalSize.sWidth"
      :height="defaultModalSize.sHeight"
      esc-closable
      transfer
      show-zoom
      resize
      :fullscreen="$store.getters.device === 'mobile'"
    >
      <div style="line-height: 3;color: #333;font-weight: 600;">打卡照片</div>
      <van-uploader capture="camera" :max-size="uploadSize" preview-size="140px" :max-count="1" v-model="fileList" @delete="imageId = ''"/>
      <p>照片大小不能超过{{ formatFileSize(uploadSize) }}</p>

      <div style="line-height: 3;color: #333;font-weight: 600;">描述</div>
      <el-input v-model="remark" type="textarea" :autosize="{ minRows: 2 }"></el-input>

      <template #footer>
        <el-button type="primary" :loading="loading" @click="outClockIn"
        >确认打卡</el-button
        >
      </template>
    </vxe-modal>
  </div>
</template>

<script>
import { index, save } from '@/api/onDutySchedules'
import { sign, preDistance, preIp, signIp } from '@/api/attendance'
import { throttle, formatFileSize } from '@/utils'
import { getToken } from '@/utils/auth'
import MonthStatics from './components/MonthStatics'
import axios from "axios";
import * as uni from "@/assets/uni.webview.1.5.6";
import { PopupManager } from "element-ui/lib/utils/popup";
import {defaultModalSize, uploadSize} from "@/settings"
export default {
  components: {
    MonthStatics
  },
  data() {
    return {
      singType: 1,
      uploadSize,
      isInUni: false,
      signStatus: 0,
      // start 外勤打卡
      loading: false,
      action: process.env.VUE_APP_UPLOAD_API,
      fileList: [],
      isShow: false,
      defaultModalSize,
      zIndex: PopupManager.nextZIndex(),
      imageId: '',
      remark: '',
      // end
      isIpSign: true,
      ipSignMsg: '',
      isGetLocation: false,
      isOutSign: false,
      pos: {
        lng: '',
        lat: '',
        address: ''
      },
      maxDistance: '',
      nowDistance: '',
      todayAttendance: {},

      // 值班
      isShowDuty: false,
      dutyDetail: {},
    }
  },
  computed: {
  },
  watch: {
    isShow(newVal) {
      if(newVal) {
        this.zIndex = PopupManager.nextZIndex()
      }
    }
  },
  methods: {
    formatFileSize,
    uploadFile(file) {
      const _this = this
      let data = new FormData()
      data.append('file', file)

      return axios.post(this.action, data, {
        'Content-type' : 'multipart/form-data',
        headers: {
          Authorization: `Bearer ${getToken()}`
        }
      }).then(res => {
        if(res.status === 200) {
          if(res.data.code) {
            Promise.reject(res.data.msg)
            return
          }
          this.imageId = res.data.data.id
        }
      }).catch(err => {
      })
    },
    outClockIn: throttle(async function() {
      try {
        this.loading = true
        if(!(this.fileList[0]?.file || this.remark)) {
          this.$message.warning('外勤打卡请拍照或者填写描述！')
          throw Error('外勤打卡请拍照或者填写描述！')
        }
        if (this.fileList[0]?.file) {
          await this.uploadFile(this.fileList[0].file)
        }

        if (this.isIpSign) {
          const res = await signIp({
            image_id: this.imageId,
            remark: this.remark,
            status: 3,
            type: this.singType
          })
        } else {
          const res = await sign({
            location: `${this.pos.lng},${this.pos.lat}`,
            address: this.pos.address,
            image_id: this.imageId,
            remark: this.remark
          })
        }
        this.$message.success('打卡成功')
        this.loading = false
        this.isShow = false
        this.fileList = []
        await this.$refs['MonthStatics'].getData()
      } catch (err) {
        console.error(err)
        this.loading = false
      }
    }, 1000, true),
    clockIn: throttle(async function(isOut=true) {
      try {
        if (!this.isInUni && !this.isIpSign) {
          await this.getLocation()
        } else if (this.isIpSign) {
          await this.preIp()
        } else if (this.isInUni) {
          uni.postMessage({
            data: {
              action: 'getLocation'
            }
          });
          return
        }
        if(!this.isGetLocation && !this.isIpSign) return
        if(isOut) {
          this.isShow = true
          return
        }
        if (this.isIpSign) {
          const res = await signIp({
            status: 1,
            type: this.singType
          })
        } else {
          const res = await sign({
            location: `${this.pos.lng},${this.pos.lat}`,
            address: this.pos.address
          })
        }
        this.$message.success('打卡成功')
        await this.$refs['MonthStatics'].getData()
      } catch (err) {
        console.error(err)
      }
    }, 1000, true),

    isAuthPermission() {
      if(!navigator.geolocation) {
        this.isGetLocation = false
        this.$msgbox.alert("您的浏览器不支持获取定位", "提示")
        this.isIpSign = true
        this.preIp()
      } else {
        this.getLocation()
      }
    },

    async getMyDuty () {
      try {
        const res = await index({
          page: 1,
          page_size: 999,
          'filter[0][key]': 'user_id',
          'filter[0][op]': 'eq',
          'filter[0][value]': this.$store.state.user.adminId,
          'filter[1][key]': 'date',
          'filter[1][op]': 'like',
          'filter[1][value]': this.$moment().format('YYYY-MM-DD'),
          'filter[2][key]': 'status',
          'filter[2][op]': 'eq',
          'filter[2][value]': '0',
        })
        if (res?.data[0]) {
          this.dutyDetail = res.data[0]
          this.isShowDuty = true
        }
      } catch(err) {
        console.error(err)
      }
    },
    async startDuty () {
      try {
        this.dutyDetail.status = 1
        await save(this.dutyDetail)
        this.$message.success("操作成功")
        await this.getMyDuty()
        this.$refs['MonthStatics'].getData()
      } catch (err) {
        console.error(err)
      }
    },

    async preIp() {
      try {
        const { result } = await preIp()
        this.signStatus = result

        // this.isOutSign = false
      } catch (err) {
        // this.isOutSign = true
      }
    },
    async pos2Address(lat, lng) {
      try {
        const res = await this.$jsonp('https://apis.map.qq.com/ws/geocoder/v1/',{
          location: lat + "," + lng,
          key: "D5EBZ-C3BWP-HZIDG-VO6BE-P2MN5-ESFZO",
          output: "jsonp"
        })
        if(!res.status) {
          this.pos.address = res.result.address
        }
      } catch (err) {
        console.error(err)
      }
    },
    async getAppLocation(latitude, longitude, first = false) {
      try {
        this.pos.lng = longitude
        this.pos.lat = latitude
        this.isIpSign = false
        this.isGetLocation = true
        if(this.pos.lat && this.pos.lng && this.isGetLocation) {
          await this.pos2Address(this.pos.lat, this.pos.lng)
          const res = await preDistance({
            location: `${this.pos.lng},${this.pos.lat}`
          })
          this.isOutSign = res.distance > Number(res.max_distance)
          this.maxDistance = res.max_distance
          this.nowDistance = res.distance

          if (first) return
          if(!this.isGetLocation) return
          if(this.isOutSign) {
            this.isShow = true
            return
          }
          const res1 = await sign({
            location: `${this.pos.lng},${this.pos.lat}`,
            address: this.pos.address
          })
          this.$message.success('打卡成功')
          await this.$refs['MonthStatics'].getData()
          console.log(res1)
        }
      } catch (err) {

      }
    },
    getLocation() {
      return new Promise((resolve, reject) => {
        if (/uni-app/.test(navigator.userAgent)) {
          this.isInUni = true
          uni.postMessage({
            data: {
              action: 'getLocation'
            }
          });
        } else {
          navigator.geolocation.getCurrentPosition((pos) => {
            this.isGetLocation = true
            this.isIpSign = false
            console.log('经度', pos.coords.latitude);
            console.log('纬度', pos.coords.longitude);
            this.pos.lng = pos.coords.longitude
            this.pos.lat = pos.coords.latitude
            if(this.pos.lat && this.pos.lng && this.isGetLocation) {
              this.pos2Address(this.pos.lat, this.pos.lng)
              preDistance({
                location: `${this.pos.lng},${this.pos.lat}`
              }).then(res => {
                this.isOutSign = res.distance	> Number(res.max_distance)
                this.maxDistance = res.max_distance
                this.nowDistance = res.distance
                resolve()
              }).catch(err => reject(err))
            }
          }, (error) => {
            console.log(error)
            this.isIpSign = true
            this.preIp()
            reject(error)
            if (error.code) {
              switch (error.code) {
                case error.PERMISSION_DENIED:
                  this.$msgbox.confirm("需授权定位后进行打卡", "提示",{
                    confirmButtonText: '重试'
                  }).then(_ => {
                    this.getLocation()
                  })
                  this.isGetLocation = false
                  break;
                case error.POSITION_UNAVAILABLE:
                  this.$msgbox.confirm("无法获取当前位置，请重试", "提示",{
                    confirmButtonText: '重试'
                  }).then(_ => {
                    this.getLocation()
                  })
                  this.isGetLocation = false
                  break;
                case error.TIMEOUT:
                  this.$msgbox.confirm("获取位置超时，请重试", "提示",{
                    confirmButtonText: '重试'
                  }).then(_ => {
                    this.getLocation()
                  })
                  this.isGetLocation = false
                  break;
                case error.UNKNOWN_ERROR:
                  this.$msgbox.confirm("获取位置错误，请重试", "提示",{
                    confirmButtonText: '重试'
                  }).then(_ => {
                    this.getLocation()
                  })
                  this.isGetLocation = false
                  break;
                default:
                  this.$msgbox.confirm("获取位置错误，请重试", "提示",{
                    confirmButtonText: '重试'
                  }).then(_ => {
                    this.getLocation()
                  })
                  this.isGetLocation = false
                  break;
              }
            }
          });
        }
      })
    },
  },
  mounted() {
    this.getMyDuty()
    this.preIp()
    // this.isAuthPermission()
  },
  created() {
    window.getAppLocation = this.getAppLocation
  }
}
</script>

<style scoped lang="scss">
.sign-btn {
  width: 6.5rem;
  height: 6.5rem;
  border-radius: 100%;
  border: none;
  display: block;
  background: var(--theme-color);
  position: relative;
  transition: all .2s;
  margin: auto;

  & > span {
    font-size: 1rem;
    font-weight: 600;
    text-align: center;
    color: #fff;

    position: relative;
  }
  &:active {
    filter: brightness(0.88);
  }
  &::before {
    content: "";
    background: var(--theme-color);
    opacity: 0.45;
    border-radius: 100%;
    animation: scale 5s infinite linear;

    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }
}
.sign-info {
  margin-top: 20px;
  display: flex;
  justify-content: center;
  padding: 0 10%;

  .sign-statue {
    line-height: 2;
    text-align: center;
    flex-basis: 50%;
  }
  .sign-log {
    flex-basis: 50%;
  }
}
@keyframes scale {
  0%,100% {
    transform: scale(1, 1);
  }
  50% {
    transform: scale(1.1, 1.1);
  }
}
@media (max-width: 992px) {
  .sign-info {
    display: block;
  }
  .sign-log {
    display: flex;
    justify-content: center;
    margin-top: 10px;
  }
}
</style>
