import { ElMessage } from 'element-plus';

// 定义扫描动作类型
type ScanAction = 'connectMessage' | 'getScannerList' | 'scanResult' | string;

// 定义接收到的消息结构
interface ScanMessage {
  code: number;
  action?: ScanAction;
  data?: any;
  message?: string;
  param?: any; // 扩展参数，用于传递额外信息
}

// 定义回调函数类型
type ScanCallback = (data: ScanMessage) => void;
type ConnectionCallback = (isOnline: boolean,clientVersion: string) => void;

class ScanCommonService {
  // 扫描客户端WebSocket 服务器地址
  private url: string = 'ws://127.0.0.1:9999'; // 扫描端口9999 图片服务端口9998

  // WebSocket 实例
  private ws: WebSocket | null = null;

  // 当前客户端连接状态
  public isOnline: boolean = false;
  public isScanned: boolean = false; // 是否有扫描仪 是否可以扫描
  public clientVersion: string = '1.0.0'; // 客户端版本号

  // 心跳定时器
  private timerPing: number | null = null;
  private timerClose: number | null = null;
  private connectionInterval: number | null = null; // 监听连接状态变化的定时器

  // 心跳间隔时间（单位：毫秒）
  private intervalPing: number = 10000; // 每隔10秒发送一次ping
  private intervalClose: number = 5000; // 等待5秒未收到pong则判定断开
  
  private isManuallyStopped: boolean = false; // 是否手动停止，防止重复连接

  /**
   * 初始化 WebSocket 连接
   * @param callback - 接收扫描结果的回调函数
   */
  init(callback?: ScanCallback): void {
    // 如果已经连接且未手动停止，不重复初始化
    if (this.ws && this.ws.readyState === WebSocket.OPEN && !this.isManuallyStopped) {
      return;
    }

    // 重置手动停止标志，允许重连
    this.isManuallyStopped = false;

    try {
      this.ws = new WebSocket(this.url);
    } catch (error) {
      console.error('WebSocket 初始化失败:', error);
      ElMessage({
        type: 'error',
        message: '无法初始化 WebSocket 连接，请检查网络设置',
        duration: 5000
      });
      return;
    }

    /**
     * WebSocket 连接建立成功时触发
     */
    this.ws.onopen = () => {
      this.isOnline = true;
      
      // 发送连接成功消息
      const sendConnectMsg = () => {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
          this.ws.send("client connect success");
        }
      };

      sendConnectMsg();
      
      // 兜底延迟发送，防止某些极端情况下的就绪延迟
      setTimeout(sendConnectMsg, 500);

      this.startHeartbeat(); // 启动心跳检测
    };

    /**
     * 接收到服务端消息时触发
     */
    this.ws.onmessage = (evt: MessageEvent) => {
      if (evt.data != null) {
        if (evt.data === "ping") {
          this.send("pong"); // 回复 pong
        } else if (evt.data === "pong") {
          // 收到 pong 不做处理，仅用于重置心跳
        } else {
          try {
            const objectData: ScanMessage = JSON.parse(evt.data);
            console.log("处理扫描结果的objectData:", objectData);
            if (objectData.code === 200) {
              if (objectData.action === 'connectMessage') {
                  
                  this.clientVersion = objectData.param.appVersion || '';
                  const version = objectData.param.appVersion || '未知版本';

                  ElMessage({
                    type: 'success',
                    message: `客户端连接成功……版本号：${version}`
                  });
              } else if (objectData.action === 'getScannerList') {
                // 获取扫描仪结果
                if (objectData.data && Array.isArray(objectData.data) && objectData.data.length > 0) {
                  // 有扫描仪连接 
                  this.isScanned = true;
                  ElMessage({
                    type: 'success',
                    message: '扫描仪连接成功……'
                  });
                } else {
                  // 没有扫描仪连接
                  this.isScanned = false;
                }
              } else {
                // 其他业务数据回调
                if (callback) callback(objectData);
              }
            } else {
              // 未检测到纸张或卡纸
              if (callback) callback(objectData);
            }
            
          } catch (error) {
            console.error("解析消息失败:", error);
          }
        }
      }
      this.resetHeartbeat(); // 重置心跳
    };

    /**
     * WebSocket 连接关闭时触发
     */
    this.ws.onclose = () => {
      this.handleOffline();
    };

    /**
     * WebSocket 发生错误时触发
     */
    this.ws.onerror = () => {
      this.isOnline = false;
      if (this.ws) {
        this.ws.close();
      }
    };
  }

  /**
   * 发送消息给 WebSocket 服务端
   * @param data - 要发送的消息内容
   */
  send(data: string): void {
    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      // 静默失败或根据需要提示
      return;
    }

    try {
      this.ws.send(data);
    } catch (e) {
      console.error("发送数据失败:", e);
      ElMessage({
        type: 'error',
        message: '发送数据失败，请检查连接状态',
        duration: 5000
      });
    }
  }

  /**
   * 启动心跳机制
   */
  private startHeartbeat(): void {
    this.clearHeartbeatTimers();

    this.timerPing = window.setTimeout(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.send("ping"); // 发送心跳 ping
        
        this.timerClose = window.setTimeout(() => {
          if (this.ws) {
            this.ws.close(); // 若长时间无响应，主动断开连接
          }
          this.isOnline = false;
          this.handleOffline(); // 处理离线逻辑
        }, this.intervalClose);
      }
    }, this.intervalPing);
  }

  /**
   * 清除心跳定时器
   */
  private clearHeartbeatTimers(): void {
    if (this.timerPing) {
      clearTimeout(this.timerPing);
      this.timerPing = null;
    }
    if (this.timerClose) {
      clearTimeout(this.timerClose);
      this.timerClose = null;
    }
  }

  /**
   * 重置心跳定时器
   */
  private resetHeartbeat(): void {
    this.clearHeartbeatTimers();
    this.startHeartbeat(); // 重新启动心跳
  }

  /**
   * 停止 WebSocket 连接并清除所有定时器
   */
  stop(): void {
    // 标记为手动停止，防止后续自动重连
    this.isManuallyStopped = true;

    // 清除心跳定时器
    this.clearHeartbeatTimers();

    // 清除连接状态监听定时器
    this.stopWatchingConnection();

    // 关闭 WebSocket 连接
    if (this.ws) {
      // 移除事件监听，防止触发 handleOffline 导致重连
      this.ws.onclose = null;
      this.ws.onerror = null;
      this.ws.onmessage = null;
      this.ws.onopen = null;
      
      if (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING) {
        this.ws.close();
      }
      this.ws = null;
    }

    // 重置连接状态
    this.isOnline = false;
    this.isScanned = false;
  }

  /**
   * 处理设备离线逻辑，尝试自动重连
   */
  private handleOffline(): void {
    this.isOnline = false;

    // 如果是手动停止，则不再尝试重连
    if (this.isManuallyStopped) {
      return;
    }

    // 延迟尝试重连
    setTimeout(() => {
      if (!this.isOnline && !this.isManuallyStopped) {
        this.init(); // 重新初始化连接
      }
    }, this.intervalClose * 2);
  }

  /**
   * 检查客户端是否已连接
   * @returns {boolean}
   */
  isClientConnected(): boolean {
    return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
  }

  /**
   * 监听连接状态变化
   * @param callback - 回调函数，接收 isOnline 布尔值参数
   */
  watchConnection(callback: ConnectionCallback): void {
    if (this.connectionInterval) {
      clearInterval(this.connectionInterval); // 防止重复启动
    }

    const checkStatus = () => {
      const isOnline = this.isClientConnected();
      
      // 调用检测扫描仪指令
      if (isOnline) {
        if (!this.isScanned) {
          // 没有扫描仪连接 实时发送指令获取状态
          const json = {
            action: 'getScannerList', // 获取扫描仪信息
          };
          this.ws?.send(JSON.stringify(json));
        }
        callback(true,this.clientVersion); // 告诉网页 客户端打开状态
      } else {
        callback(false,this.clientVersion); // 告诉网页 连接已经断开
      }
    };

    checkStatus(); // 立即执行一次
    this.connectionInterval = window.setInterval(checkStatus, 3000); // 每3秒检测一次
  }

  /**
   * 停止监听连接状态
   */
  stopWatchingConnection(): void {
    if (this.connectionInterval) {
      clearInterval(this.connectionInterval);
      this.connectionInterval = null;
    }
  }
}

// 导出单例
const scanCommon = new ScanCommonService();
export default scanCommon;