/**
 * 时间服务模块
 * 提供准确的服务器时间，避免依赖设备本地时间和时区
 */
import { getServerTime } from "@/api/oa/attendance/clockIn";

class TimeService {
  constructor() {
    // 服务器基准时间信息
    this.serverBaseTime = {
      year: 0,
      month: 0,
      day: 0,
      hour: 0,
      minute: 0,
      second: 0,
      timestamp: 0
    };
    // 本地性能计时器基准点（performance.now()的值）
    this.performanceTimeBase = 0;
    // 最后一次同步的performance时间
    this.lastSyncPerformanceTime = 0;
    // 同步间隔（5分钟）
    this.syncInterval = 5 * 60 * 1000;
    // 是否正在同步
    this.syncing = false;
    // 是否已成功同步过服务器时间
    this.hasSyncedServer = false;
    // 时间更新回调函数列表
    this.updateCallbacks = [];
    // 更新循环是否已启动
    this.updateLoopStarted = false;
  }

  /**
   * 解析服务器时间字符串为时间组件
   * @param {string} timeString 时间字符串 (YYYY-MM-DD HH:mm:ss 格式)
   * @returns {Object} 时间组件对象
   */
  parseTimeString(timeString) {
    const parts = timeString.split(' ');
    const datePart = parts[0].split('-');
    const timePart = parts[1].split(':');
    
    return {
      year: parseInt(datePart[0]),
      month: parseInt(datePart[1]),
      day: parseInt(datePart[2]),
      hour: parseInt(timePart[0]),
      minute: parseInt(timePart[1]),
      second: parseInt(timePart[2]),
      timestamp: new Date(timeString.replace(/-/g, '/')).getTime()
    };
  }

  /**
   * 格式化时间组件为字符串
   * @param {Object} timeComponents 时间组件
   * @returns {string} 格式化的时间字符串
   */
  formatTimeComponents(timeComponents) {
    const pad = (num) => String(num).padStart(2, '0');
    return `${timeComponents.year}-${pad(timeComponents.month)}-${pad(timeComponents.day)} ${pad(timeComponents.hour)}:${pad(timeComponents.minute)}:${pad(timeComponents.second)}`;
  }

  /**
   * 给时间组件添加毫秒数（纯数学计算，不依赖Date对象）
   * @param {Object} baseTime 基准时间组件
   * @param {number} milliseconds 要添加的毫秒数
   * @returns {Object} 新的时间组件
   */
  addMilliseconds(baseTime, milliseconds) {
    // 复制基准时间
    let result = { ...baseTime };
    
    // 将毫秒转换为秒并添加
    const totalSeconds = Math.floor(milliseconds / 1000);
    result.second += totalSeconds;
    
    // 处理秒的进位
    if (result.second >= 60) {
      const additionalMinutes = Math.floor(result.second / 60);
      result.second = result.second % 60;
      result.minute += additionalMinutes;
    }
    
    // 处理分钟的进位
    if (result.minute >= 60) {
      const additionalHours = Math.floor(result.minute / 60);
      result.minute = result.minute % 60;
      result.hour += additionalHours;
    }
    
    // 处理小时的进位
    if (result.hour >= 24) {
      const additionalDays = Math.floor(result.hour / 24);
      result.hour = result.hour % 24;
      result.day += additionalDays;
      
      // 处理跨月、跨年的复杂情况（简化处理）
      // 这里可以根据需要进一步完善
      result = this.handleDayOverflow(result);
    }
    
    // 更新时间戳
    result.timestamp = baseTime.timestamp + milliseconds;
    
    return result;
  }

  /**
   * 处理日期的进位（月、年）
   * @param {Object} timeComponents 时间组件
   * @returns {Object} 处理后的时间组件
   */
  handleDayOverflow(timeComponents) {
    const daysInMonth = this.getDaysInMonth(timeComponents.year, timeComponents.month);
    
    if (timeComponents.day > daysInMonth) {
      const monthsToAdd = Math.floor((timeComponents.day - 1) / daysInMonth);
      timeComponents.day = ((timeComponents.day - 1) % daysInMonth) + 1;
      timeComponents.month += monthsToAdd;
      
      if (timeComponents.month > 12) {
        const yearsToAdd = Math.floor((timeComponents.month - 1) / 12);
        timeComponents.month = ((timeComponents.month - 1) % 12) + 1;
        timeComponents.year += yearsToAdd;
      }
    }
    
    return timeComponents;
  }

  /**
   * 获取指定年月的天数
   * @param {number} year 年份
   * @param {number} month 月份 (1-12)
   * @returns {number} 该月的天数
   */
  getDaysInMonth(year, month) {
    // 使用数组而不是Date对象来避免时区问题
    const daysInMonths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    
    if (month === 2 && this.isLeapYear(year)) {
      return 29;
    }
    
    return daysInMonths[month - 1];
  }

  /**
   * 判断是否为闰年
   * @param {number} year 年份
   * @returns {boolean} 是否为闰年
   */
  isLeapYear(year) {
    return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
  }

  /**
   * 同步服务器时间
   * @returns {Promise<boolean>} 同步是否成功
   */
  async syncServerTime() {
    if (this.syncing) {
      return false;
    }

    this.syncing = true;

    try {
      const syncStartPerformance = performance.now();
      const response = await getServerTime();
      const syncEndPerformance = performance.now();

      if (response.code === 200 && response.data) {
        console.log(response.data);
        
        // 计算网络延迟
        const networkDelay = (syncEndPerformance - syncStartPerformance) / 2;
        
        // 解析服务器时间并添加网络延迟补偿
        this.serverBaseTime = this.parseTimeString(response.data);
        this.serverBaseTime = this.addMilliseconds(this.serverBaseTime, networkDelay);
        
        // 记录performance基准时间点
        this.performanceTimeBase = syncEndPerformance;
        this.lastSyncPerformanceTime = syncEndPerformance;
        this.hasSyncedServer = true;

        console.log("服务器时间同步成功", {
          serverTime: this.formatTimeComponents(this.serverBaseTime),
          performanceBase: this.performanceTimeBase,
          networkDelay,
        });

        return true;
      }
    } catch (error) {
      console.warn("服务器时间同步失败，将使用本地时间：", error.message);
    } finally {
      this.syncing = false;
    }

    return false;
  }

  /**
   * 获取当前时间组件
   * @returns {Object} 当前时间组件
   */
  getCurrentTimeComponents() {
    const currentPerformanceTime = performance.now();

    // 检查是否需要重新同步（基于performance时间）
    if (this.hasSyncedServer && 
        currentPerformanceTime - this.lastSyncPerformanceTime > this.syncInterval) {
      // 异步同步，不阻塞当前调用
      this.syncServerTime();
    }

    // 如果已同步过服务器时间，使用服务器时间基准
    if (this.hasSyncedServer) {
      // 计算从基准点开始经过的时间
      const elapsedTime = currentPerformanceTime - this.performanceTimeBase;
      return this.addMilliseconds(this.serverBaseTime, elapsedTime);
    }

    // 降级到本地时间（解析当前本地时间）
    const now = new Date();
    const year = now.getFullYear();
    const month = now.getMonth() + 1;
    const day = now.getDate();
    const hour = now.getHours();
    const minute = now.getMinutes();
    const second = now.getSeconds();
    
    return {
      year, month, day, hour, minute, second,
      timestamp: now.getTime()
    };
  }

  /**
   * 获取当前准确时间（兼容性方法）
   * @returns {Date} 当前时间Date对象
   */
  getCurrentTime() {
    const timeComponents = this.getCurrentTimeComponents();
    return new Date(timeComponents.timestamp);
  }

  /**
   * 获取格式化的当前时间字符串（用于显示）
   * @returns {string} HH:mm:ss 格式的时间
   */
  getCurrentTimeString() {
    const timeComponents = this.getCurrentTimeComponents();
    const pad = (num) => String(num).padStart(2, "0");
    return `${pad(timeComponents.hour)}:${pad(timeComponents.minute)}:${pad(timeComponents.second)}`;
  }

  /**
   * 获取完整的当前日期时间字符串（用于提交）
   * @returns {string} YYYY-MM-DD HH:mm:ss 格式的时间
   */
  getCurrentDateTimeString() {
    const timeComponents = this.getCurrentTimeComponents();
    const pad = (num) => String(num).padStart(2, "0");
    
    return `${timeComponents.year}-${pad(timeComponents.month)}-${pad(timeComponents.day)} ${pad(timeComponents.hour)}:${pad(timeComponents.minute)}:${pad(timeComponents.second)}`;
  }

  /**
   * 比较当前时间与计划时间
   * @param {string} scheduleTime 计划时间 (HH:mm格式)
   * @returns {number} 比较结果 (-1: 早于, 0: 等于, 1: 晚于)
   */
  compareTimeWithSchedule(scheduleTime) {
    const timeComponents = this.getCurrentTimeComponents();
    const [scheduleHour, scheduleMinute] = scheduleTime.split(":").map(Number);

    const currentMinutes = timeComponents.hour * 60 + timeComponents.minute;
    const scheduleMinutes = scheduleHour * 60 + scheduleMinute;

    return Math.sign(currentMinutes - scheduleMinutes);
  }

  /**
   * 初始化时间服务
   * @returns {Promise<boolean>} 返回初始同步是否成功
   */
  async initialize() {
    const syncSuccess = await this.syncServerTime();

    // 使用基于performance时间的定期同步检查
    // 而不是依赖系统时间的setInterval
    this.startPeriodicSync();

    return syncSuccess;
  }

  /**
   * 启动基于performance时间的定期同步
   * 避免受设备时间修改影响
   */
  startPeriodicSync() {
    const checkSync = () => {
      const currentPerformanceTime = performance.now();
      
      // 如果距离上次同步超过间隔时间，执行同步
      if (this.hasSyncedServer && 
          currentPerformanceTime - this.lastSyncPerformanceTime > this.syncInterval) {
        this.syncServerTime();
      }
      
      // 每30秒检查一次是否需要同步
      setTimeout(checkSync, 30 * 1000);
    };
    
    // 30秒后开始第一次检查
    setTimeout(checkSync, 30 * 1000);
  }

  /**
   * 添加时间更新回调
   * @param {Function} callback 回调函数
   * @returns {Function} 用于移除回调的函数
   */
  onTimeUpdate(callback) {
    this.updateCallbacks.push(callback);
    
    // 启动更新循环（如果还没启动）
    if (!this.updateLoopStarted) {
      this.startUpdateLoop();
    }
    
    // 返回移除回调的函数
    return () => {
      const index = this.updateCallbacks.indexOf(callback);
      if (index > -1) {
        this.updateCallbacks.splice(index, 1);
      }
    };
  }

  /**
   * 启动基于requestAnimationFrame的更新循环
   * 确保稳定的1秒更新频率，不受系统时间影响
   */
  startUpdateLoop() {
    if (this.updateLoopStarted) return;
    
    this.updateLoopStarted = true;
    let lastUpdateTime = performance.now();
    
    const updateLoop = () => {
      const currentTime = performance.now();
      
      // 每秒触发一次更新（基于performance时间）
      if (currentTime - lastUpdateTime >= 1000) {
        // 执行所有回调
        this.updateCallbacks.forEach(callback => {
          try {
            callback();
          } catch (error) {
            console.error('时间更新回调执行失败:', error);
          }
        });
        
        lastUpdateTime = currentTime;
      }
      
      requestAnimationFrame(updateLoop);
    };
    
    requestAnimationFrame(updateLoop);
  }
}

// 创建全局时间服务实例
const timeService = new TimeService();

export default timeService;
