<!--
打卡业务流程：
登录 -> 考勤打卡 -> 获取当前员工考勤组 -> 打卡

功能说明：
1. 获取考勤组信息：上班、下班时间、考勤范围
2. 上班打卡：直接打卡/迟到打卡（填写备注）
3. 下班打卡：直接打卡/早退打卡（填写备注）/更新打卡
-->
<template>
  <div class="page">
    <div
      v-if="attendanceGroup.attendanceGroupName"
      class="container"
      :class="{ 'has-birthday': hasBirthday }"
    >
      <!-- 用户信息头部 -->
      <div class="header">
        <div class="user-info">
          <div class="user-left">
            <div class="avatar">
              <el-avatar :src="userinfo.avatar">{{
                userinfo.nickName
              }}</el-avatar>
            </div>
            <div class="user-name">{{ userinfo.nickName }}</div>
          </div>
          <div class="user-right">
            <div class="user-department">
              {{ userinfo.dept.deptName
              }}<em v-if="userinfo.language">({{ userinfo.language }})</em>
            </div>
          </div>
        </div>

        <!-- 打卡状态卡片 -->
        <div class="status-cards">
          <div class="status-card">
            <div class="status-time">
              <!-- 上班 -->
              {{ getCheckInStatusText('clockIn') }}
              {{ formatTime(attendanceStatus.clockInTime) }}
            </div>
            <div class="status-label">
              <span>{{ $t('checkin.workStartTime') }} {{ attendanceGroup.workStartTime }}</span>
            </div>
          </div>
          <div class="status-card">
            <div class="status-time">
              <!-- 下班 -->
              {{ getCheckInStatusText('clockOut') }}
              {{ formatTime(attendanceStatus.clockOutTime) }}
            </div>
            <div class="status-label">
              <span>{{ $t('checkin.workEndTime') }} {{ attendanceGroup.workEndTime }}</span>
            </div>
          </div>
        </div>

        <p v-if="hasBirthday" class="birthday-message">
          🎂{{ birthdayMessage }}🎉🎁🎈
        </p>
      </div>

      <!-- 打卡按钮 -->
      <div class="punch-section">
        <div
          class="punch-button"
          :class="{ 'is-disabled': !isInRange }"
          @click="handlePunchClick"
        >
          <div class="punch-text">{{ punchButtonText }}</div>
          <div class="punch-zone">{{ timeZone }}</div>
          <div class="punch-time">{{ currentTime }}</div>
        </div>
      </div>

      <!-- 备注弹出层 -->
      <remark-dialog
        :visible="showRemarkDialog"
        :title="remarkDialogTitle"
        :remark="remarkForm.remark"
        @close="closeRemarkDialog"
        @submit="submitRemarkPunch"
        @update:remark="remarkForm.remark = $event"
      />

      <!-- 打卡成功提示 -->
      <!-- <success-dialog
        :visible="showSuccessDialog"
        :punch-time="currentCompleteDate"
        :location="attendanceGroup.areaName"
        @close="closeSuccessDialog"
      /> -->

      <!-- 打卡成功提示 -->
      <success-dialog
        :visible="showSuccessDialog"
        :punch-time="currentCompleteDate"
        :location="formattedAddress"
        @close="closeSuccessDialog"
      />

      <!-- 位置信息显示 -->
      <location-info
        :is-in-range="isInRange"
        :area-name="attendanceGroup.areaName"
        :longitude="userLocation.longitude"
        :latitude="userLocation.latitude"
      />
    </div>

    <!-- 加载状态 -->
    <div v-else class="container loading">
      <div class="loading-text">
        <!-- 正在加载考勤信息... -->
        <i class="el-icon-loading" />
      </div>
    </div>
  </div>
</template>
<script>
import { mapGetters } from 'vuex'
import { AttendanceService, PUNCH_STATUS, PUNCH_TYPE } from './service'
import RemarkDialog from './components/RemarkDialog.vue'
import SuccessDialog from './components/SuccessDialog.vue'
import LocationInfo from './components/LocationInfo.vue'
import { getGeocode } from '@/api/oa/attendance/clockIn'
import moment from 'moment'
import timeService from '@/utils/timeService'
import ResizeMixin from '@/layout/mixin/ResizeHandler'

export default {
  name: 'MCheckin',
  components: {
    RemarkDialog,
    SuccessDialog,
    LocationInfo
  },
  mixins: [ResizeMixin],
  data() {
    return {
      // 时间相关
      currentTime: '',
      currentCompleteDate: '',
      removeTimeUpdateCallback: null,

      // 打卡成功地址
      formattedAddress: '',

      // 位置相关
      userLocation: {
        latitude: null,
        longitude: null
      },
      isInRange: false,
      watchId: null,

      // 考勤数据
      attendanceGroup: {},
      attendanceStatus: {
        clockInTime: null,
        clockOutTime: null,
        clockInStatus: PUNCH_STATUS.NOT_CHECKED,
        clockOutStatus: PUNCH_STATUS.NOT_CHECKED
      },

      // 弹窗状态
      showRemarkDialog: false,
      showSuccessDialog: false,
      remarkDialogTitle: '',
      remarkForm: {
        remark: '',
        type: ''
      },
      isPC: false
    }
  },

  computed: {
    ...mapGetters(['userinfo', 'nickname']),

    hasBirthday() {
      if (!this.userinfo.birthday) return false
      // 使用服务器时间组件而不是系统时间
      const timeComponents = timeService.getCurrentTimeComponents()
      const birthday = this.userinfo.birthday.split('-')

      const month = birthday[1]
      const day = birthday[2]

      const todayMonth = String(timeComponents.month).padStart(2, '0')
      const todayDay = String(timeComponents.day).padStart(2, '0')

      return month == todayMonth && day == todayDay
    },
    birthdayMessage() {
      if (!this.userinfo.birthday) return ''
      return this.$t('home.birthday', {
        name: this.nickname,
        birthday: moment(this.userinfo.birthday).format(`M/D`)
      })
    },

    /**
     * 获取当前时区，根据考勤组时区
     * @returns {string} 时区信息
     */
    timeZone() {
      return (
        this.attendanceGroup.timeZone ||
        Intl.DateTimeFormat().resolvedOptions().timeZone
      )
    },

    /**
     * 获取打卡按钮文本
     * @returns {string} 按钮文本
     */
    punchButtonText() {
      const { clockInStatus, clockOutStatus } = this.attendanceStatus

      console.log(PUNCH_STATUS)

      if (clockInStatus == PUNCH_STATUS.NOT_CHECKED) {
        // return '上班打卡'
        return this.$t('checkin.button.notChecked')
      }
      if (
        clockOutStatus == PUNCH_STATUS.NOT_CHECKED ||
        clockOutStatus == PUNCH_STATUS.CHECKED_OUT ||
        clockOutStatus == PUNCH_STATUS.LATE_IN
      ) {
        // return '下班打卡'
        return this.$t('checkin.button.checkedIn')
      }
      // return '已打卡'
      return this.$t('checkin.button.checkedOut')
    }
  },

  async mounted() {
    try {
      if (this.userinfo.language) {
        this.$i18n.locale = this.userinfo.language
        this.$store.dispatch('language/setLanguage', this.userinfo.language)
      }
      // 判断如果是PC端
      if (!this.$_isMobile()) {
        this.$alert(this.$t('checkin.error.pcMessage'), this.$t('checkin.error.message'), {
          confirmButtonText: this.$t('checkin.error.confirm'),
          showCancelButton: false,
          closeOnClickModal: false,
          closeOnPressEscape: false,
          showClose: false,
          center: true,
          callback: () => {
            this.$router.push('/')
          }
        })
        return
      } else {
        await this.initializeApp()
      }
    } catch (error) {
      // this.handleError(this.$i18n.t("checkin.error.init"), error);
    }
  },

  beforeDestroy() {
    this.cleanup()
  },

  methods: {
    /**
     * 初始化应用
     */
    async initializeApp() {
      // 初始化时间服务（获取服务器时间）
      try {
        const syncSuccess = await timeService.initialize()
        if (!syncSuccess) {
          console.warn('服务器时间同步失败，将使用设备本地时间')
          // 可以选择性地显示警告提示
          // this.$toast.warning('时间同步失败，请确保网络连接正常');
        }
      } catch (error) {
        console.error('时间服务初始化失败：', error)
        // 降级到本地时间，不影响正常功能
      }

      this.startTimeUpdate()
      await this.startLocationTracking()
      await this.loadAttendanceData()
    },

    /**
     * 开始时间更新（使用稳定的服务器时间更新机制）
     */
    startTimeUpdate() {
      this.updateCurrentTime()
      // 使用timeService的稳定更新回调，不受系统时间影响
      this.removeTimeUpdateCallback = timeService.onTimeUpdate(() => {
        this.updateCurrentTime()
      })
    },

    /**
     * 更新当前时间显示（使用服务器时间）
     */
    updateCurrentTime() {
      this.currentTime = timeService.getCurrentTimeString()
    },

    /**
     * 开始位置跟踪
     */
    async startLocationTracking() {
      const options = {
        enableHighAccuracy: true,
        timeout: 5000,
        maximumAge: 0
      }

      this.watchId = navigator.geolocation.watchPosition(
        this.handleLocationSuccess,
        this.handleLocationError,
        options
      )
    },

    /**
     * 处理位置获取成功
     * @param {GeolocationPosition} position 位置信息
     */
    handleLocationSuccess(position) {
      this.userLocation = {
        latitude: position.coords.latitude,
        longitude: position.coords.longitude
      }
      this.updateLocationRange()
    },

    /**
     * 处理位置获取失败
     * @param {GeolocationPositionError} error 错误信息
     */
    handleLocationError(error) {
      const errorMessages = {
        [error.PERMISSION_DENIED]: '请允许获取位置权限',
        [error.POSITION_UNAVAILABLE]: '位置信息不可用',
        [error.TIMEOUT]: '获取位置超时'
      }

      const message = errorMessages[error.code] || '获取位置失败'
      this.$toast.error(message)
    },

    /**
     * 更新是否在打卡范围内
     */
    updateLocationRange() {
      this.isInRange = AttendanceService.isInAttendanceRange(
        this.userLocation,
        this.attendanceGroup
      )
    },

    /**
     * 加载考勤数据
     */
    async loadAttendanceData() {
      const { userId } = this.userinfo
      if (!userId) {
        throw new Error('用户信息获取失败')
      }

      await Promise.all([
        this.loadAttendanceGroup(userId),
        this.loadTodayAttendance(userId)
      ])
    },

    /**
     * 加载考勤组信息
     * @param {string} userId 用户ID
     */
    async loadAttendanceGroup(userId) {
      this.attendanceGroup = await AttendanceService.getAttendanceGroup(userId)
      this.updateLocationRange()
    },

    /**
     * 加载今日考勤记录
     * @param {string} userId 用户ID
     */
    async loadTodayAttendance(userId) {
      const records = await AttendanceService.getTodayAttendance(userId)
      this.attendanceStatus =
        AttendanceService.processAttendanceRecords(records)
    },

    /**
     * 处理打卡按钮点击
     */
    async handlePunchClick() {
      if (!this.validatePunchConditions()) {
        return
      }

      try {
        const punchAction = this.determinePunchAction()
        await this.executePunchAction(punchAction)
      } catch (error) {
        this.handleError('打卡失败', error)
      }
    },

    /**
     * 验证打卡条件
     * @returns {boolean} 是否可以打卡
     */
    validatePunchConditions() {
      if (!this.isInRange) {
        // this.$toast.error("请在打卡范围内进行打卡");
        this.$toast.error(this.$t('checkin.error.outOfRange'))
        return false
      }

      const { clockInStatus, clockOutStatus } = this.attendanceStatus
      if (
        clockInStatus !== PUNCH_STATUS.NOT_CHECKED &&
        clockOutStatus !== PUNCH_STATUS.NOT_CHECKED
      ) {
        // this.$toast.info("今日已完成打卡");
        this.$toast.info(this.$t('checkin.punch.status.todayChecked'))
        return false
      }

      return true
    },

    /**
     * 确定打卡动作类型
     * @returns {Object} 打卡动作信息
     */
    determinePunchAction() {
      const { clockInStatus } = this.attendanceStatus

      if (clockInStatus === PUNCH_STATUS.NOT_CHECKED) {
        return AttendanceService.isLateForWork(
          this.attendanceGroup.workStartTime
        )
          ? { type: 'morning_late', needRemark: true }
          : { type: 'morning', needRemark: false }
      }

      return AttendanceService.isEarlyForLeaving(
        this.attendanceGroup.workEndTime
      )
        ? { type: 'evening_early', needRemark: true }
        : { type: 'evening', needRemark: false }
    },

    /**
     * 执行打卡动作
     * @param {Object} action 打卡动作信息
     */
    async executePunchAction(action) {
      if (action.needRemark) {
        this.showRemarkDialogForType(action.type)
      } else {
        await this.submitPunch(action.type)
      }
    },

    /**
     * 显示备注对话框
     * @param {string} type 打卡类型
     */
    showRemarkDialogForType(type) {
      // const titles = {
      //   morning_late: "迟到打卡",
      //   evening_early: "早退打卡",
      // };

      const titles = {
        morning_late: this.$t('checkin.punch.status.lateIn'),
        evening_early: this.$t('checkin.punch.status.earlyOut')
      }

      this.remarkDialogTitle = titles[type]
      this.remarkForm.type = type
      this.remarkForm.remark = ''
      this.showRemarkDialog = true
    },

    /**
     * 提交备注打卡
     */
    async submitRemarkPunch() {
      try {
        await this.submitPunch(this.remarkForm.type)
        this.closeRemarkDialog()
      } catch (error) {
        // this.handleError("提交失败", error);
        this.handleError(this.$t('checkin.error.submitFailed'), error)
      }
    },

    /**
     * 提交打卡请求
     * @param {string} type 打卡类型
     */
    async submitPunch(type) {
      const punchData = AttendanceService.buildPunchData({
        type,
        userInfo: this.userinfo,
        userLocation: this.userLocation,
        attendanceGroupId: this.attendanceGroup.attendanceGroupId,
        attendanceGroupName: this.attendanceGroup.attendanceGroupName,
        remark: this.remarkForm.remark
      })

      await AttendanceService.submitPunch(punchData)

      this.currentCompleteDate = AttendanceService.formatDateTime()
      this.showSuccessDialog = true
      this.formattedAddress = 'Loading...'

      try {
        const res = await getGeocode(
          this.userLocation.longitude,
          this.userLocation.latitude
        )
        console.log(res)
        const { status, results } = res
        if (status.code === 200 && results.length > 0) {
          const { formatted } = results[0]
          this.formattedAddress = formatted
        }
      } catch (error) {
        this.formattedAddress = this.attendanceGroup.areaName
        console.error(error)
      }

      await this.loadTodayAttendance(this.userinfo.userId)
    },

    /**
     * 获取打卡状态文本
     * @param {string} type 打卡类型
     * @returns {string} 状态文本
     */
    getCheckInStatusText(type) {
      const status =
        type === PUNCH_TYPE.CLOCK_IN
          ? this.attendanceStatus.clockInStatus
          : this.attendanceStatus.clockOutStatus

      return AttendanceService.getStatusText(status)
    },

    /**
     * 格式化时间显示
     * @param {string} time 时间字符串
     * @returns {string} 格式化后的时间
     */
    formatTime(time) {
      return AttendanceService.formatTime(time)
    },

    /**
     * 关闭备注对话框
     */
    closeRemarkDialog() {
      this.showRemarkDialog = false
      this.remarkForm.remark = ''
    },

    /**
     * 关闭成功对话框
     */
    closeSuccessDialog() {
      this.showSuccessDialog = false
    },

    /**
     * 统一错误处理
     * @param {string} message 错误消息
     * @param {Error} error 错误对象
     */
    handleError(message, error) {
      console.error(message, error)
      this.$toast.error(error.message || message)
    },

    /**
     * 清理资源
     */
    cleanup() {
      if (this.watchId !== null) {
        navigator.geolocation.clearWatch(this.watchId)
      }
      if (this.removeTimeUpdateCallback) {
        this.removeTimeUpdateCallback()
      }
    }
  }
}
</script>
<style lang="scss" scoped>
.page {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  min-height: 100vh;
  color: #333;
  @media (min-width: 480px) {
    width: 480px;
    margin: 0 auto;
    border-radius: 10px;
  }
}

.container {
  margin: 0 auto;
  background: #f5f5f5;
  min-height: 100vh;
  position: relative;
  user-select: none;

  &.has-birthday {
    background: linear-gradient(135deg, #ffd6e8, #fff3b0, #b5ead7, #c9f0ff);
    background-size: 400% 400%;
    animation: birthdayGradient 15s ease infinite;

    .header {
      background: rgba(255, 255, 255, 0.4);
      box-shadow: none;
    }

    .status-card {
      background: rgba(255, 255, 255, 0.4);
      box-shadow: none;
    }

    ::v-deep .location-info {
      background: rgba(255, 255, 255, 0.4);
      box-shadow: none;
    }
  }

  &.loading {
    display: flex;
    align-items: center;
    justify-content: center;
  }
}

@keyframes birthdayGradient {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

.loading-text {
  font-size: 16px;
  color: #666;
  text-align: center;
}

.header {
  padding: 20px;
  background: white;
  border-radius: 0 0 20px 20px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.footer {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 10px;
  text-align: center;
  background: white;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.user-info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}

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

.avatar {
  width: 50px;
  height: 50px;
  background: #2196f3;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 18px;
  font-weight: bold;
  margin-right: 15px;

  .el-avatar {
    background: #2196f3;
  }
}

.user-name {
  font-size: 20px;
  font-weight: 600;
  color: #333;
}

.user-department {
  font-size: 14px;
  color: #666;
}

.status-cards {
  display: flex;
  justify-content: space-between;
  gap: 10px;
}

.status-card {
  flex: 1;
  background: #f8f9fa;
  padding: 15px;
  border-radius: 12px;
  text-align: center;
}

.status-time {
  font-size: 15px;
  font-weight: 600;
  margin-bottom: 5px;
}

.status-label {
  font-size: 12px;
  color: #666;

  span {
    display: block;
    margin-bottom: 2px;

    &:last-child {
      margin-bottom: 0;
    }
  }
}

.punch-section {
  padding: 40px 20px;
  text-align: center;
}

.punch-button {
  width: 180px;
  height: 180px;
  background: linear-gradient(135deg, #2196f3, #21cbf3);
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
  box-shadow: 0 8px 25px rgba(33, 150, 243, 0.3);
  cursor: pointer;
  transition: all 0.3s ease;

  &.is-disabled {
    background: linear-gradient(135deg, #b0bec5, #90a4ae);
    box-shadow: 0 8px 25px rgba(176, 190, 197, 0.3);
    cursor: not-allowed;
    opacity: 0.8;

    .punch-text,
    .punch-zone,
    .punch-time {
      opacity: 0.8;
    }

    &:active {
      transform: none;
    }
  }

  &:focus,
  &:active:not(.is-disabled) {
    transform: scale(1.05);
  }
}

.punch-text {
  color: white;
  font-size: 20px;
  font-weight: 600;
  margin-bottom: 5px;
}

.punch-zone {
  color: rgba(255, 255, 255, 0.8);
  font-size: 10px;
}

.punch-time {
  color: rgba(255, 255, 255, 0.8);
  font-size: 18px;
  font-weight: 600;
}
</style>
