// WebSocket全局配置
const WS_CONFIG = {
  heartbeatInterval: 10000, // 30秒心跳间隔
  heartbeatTimeout: 10000, // 心跳响应超时时间（10秒，给服务器更多响应时间）
  maxReconnectAttempts: 5, // 最大重连次数
  reconnectBaseDelay: 500, // 重连基础延迟0.5秒（更快重连）
  maxReconnectDelay: 10000, // 最大重连延迟10秒（减少等待时间）
  heartbeatMessage: 'ping', // 心跳消息
  heartbeatResponseType: 'pong', // 心跳响应类型
};

// 增强的WebSocket包装器
class EnhancedWebSocket {
  private ws: WebSocket;
  private path: string;
  private baseUrl: string;
  private heartbeatTimer?: NodeJS.Timeout;
  private heartbeatTimeoutTimer?: NodeJS.Timeout;
  private reconnectTimer?: NodeJS.Timeout;
  private reconnectAttempts: number = 0;
  private isManualClose: boolean = false;
  private isHeartbeatTimeout: boolean = false;
  private userOnMessage: ((event: MessageEvent) => void) | null = null;
  private userOnClose: ((event: CloseEvent) => void) | null = null;
  private userOnError: ((event: Event) => void) | null = null;
  private userOnOpen: ((event: Event) => void) | null = null;

  constructor(path: string, baseUrl: string) {
    this.path = path;
    this.baseUrl = baseUrl;
    this.ws = new WebSocket(baseUrl + path);
    this.setupHandlers();
  }

  // 设置事件处理器
  private setupHandlers(): void {
    this.ws.onopen = (event) => {
      console.log(`WebSocket连接已建立: ${this.path}`);
      this.reconnectAttempts = 0;
      this.clearReconnectTimer();

      // 🔧 优化：连接建立后立即发送一次心跳，然后开始定期心跳
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(WS_CONFIG.heartbeatMessage);
        this.startHeartbeatTimeout();
      }
      this.startHeartbeat();

      if (this.userOnOpen) {
        this.userOnOpen(event);
      }
    };

    this.ws.onmessage = (event) => {
      const messageData = event.data;

      // 🔧 优化：收到任何消息都说明连接正常，清除心跳超时检测
      this.clearHeartbeatTimeout();

      // 检查是否为心跳响应（支持字符串和JSON格式）
      let isHeartbeatResponse = false;

      // 1. 检查是否为简单字符串心跳响应
      if (typeof messageData === 'string' && messageData === WS_CONFIG.heartbeatResponseType) {
        isHeartbeatResponse = true;
      }

      // 2. 检查是否为JSON格式心跳响应
      if (!isHeartbeatResponse && typeof messageData === 'string') {
        try {
          const data = JSON.parse(messageData);
          if (data.type === WS_CONFIG.heartbeatResponseType) {
            isHeartbeatResponse = true;
          }
        } catch (e) {
          // JSON解析失败，不是JSON格式的心跳响应
        }
      }

      if (isHeartbeatResponse) {
        // 心跳响应，不传递给业务代码
        return;
      }

      // 传递给业务代码
      if (this.userOnMessage) {
        this.userOnMessage(event);
      }
    };

    this.ws.onclose = (event) => {
      console.log(`WebSocket连接关闭: ${this.path}`, event.code, event.reason);
      this.stopHeartbeat();

      // 先调用业务代码的关闭处理
      if (this.userOnClose) {
        this.userOnClose(event);
      }

      // 如果不是手动关闭，或者是心跳超时导致的关闭，则重连
      if (!this.isManualClose || this.isHeartbeatTimeout) {
        this.scheduleReconnect();
      }

      // 重置心跳超时标志
      this.isHeartbeatTimeout = false;
    };

    this.ws.onerror = (event) => {
      console.error(`WebSocket连接错误: ${this.path}`, event);
      this.stopHeartbeat();

      if (this.userOnError) {
        this.userOnError(event);
      }
    };
  }

  // 开始心跳检测
  private startHeartbeat(): void {
    this.stopHeartbeat();
    console.log(`开始心跳检测: ${this.path}, 间隔: ${WS_CONFIG.heartbeatInterval}ms`);
    this.heartbeatTimer = setInterval(() => {
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(WS_CONFIG.heartbeatMessage);

        // 只有在没有进行超时检测时才设置新的超时检测
        if (!this.heartbeatTimeoutTimer) {
          this.startHeartbeatTimeout();
        }
      }
    }, WS_CONFIG.heartbeatInterval);
  }

  // 停止心跳检测
  private stopHeartbeat(): void {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = undefined;
    }
    this.clearHeartbeatTimeout();
  }

  // 开始心跳响应超时检测
  private startHeartbeatTimeout(): void {
    // 不再自动清除，只在收到响应时清除
    this.heartbeatTimeoutTimer = setTimeout(() => {
      console.log(`心跳响应超时: ${this.path}, ${WS_CONFIG.heartbeatTimeout}ms内未收到响应，主动断开连接`);
      // 设置心跳超时标志，触发重连
      this.isHeartbeatTimeout = true;
      this.ws.close(1000, 'Heartbeat timeout'); // 使用正常关闭状态码，通过标志来判断是否重连
    }, WS_CONFIG.heartbeatTimeout);
  }

  // 清除心跳响应超时检测
  private clearHeartbeatTimeout(): void {
    if (this.heartbeatTimeoutTimer) {
      clearTimeout(this.heartbeatTimeoutTimer);
      this.heartbeatTimeoutTimer = undefined;
    }
  }

  // 安排重连
  private scheduleReconnect(): void {
    if (this.isManualClose || this.reconnectAttempts >= WS_CONFIG.maxReconnectAttempts) {
      console.log(`停止重连: ${this.path}, 手动关闭: ${this.isManualClose}, 重连次数: ${this.reconnectAttempts}`);
      return;
    }

    this.reconnectAttempts++;

    // 指数退避重连策略
    const delay = Math.min(
      WS_CONFIG.reconnectBaseDelay * Math.pow(2, this.reconnectAttempts - 1),
      WS_CONFIG.maxReconnectDelay,
    );

    console.log(
      `WebSocket将在${delay}ms后重连: ${this.path} (${this.reconnectAttempts}/${WS_CONFIG.maxReconnectAttempts})`,
    );

    this.reconnectTimer = setTimeout(() => {
      this.reconnect();
    }, delay);
  }

  // 重连逻辑
  private reconnect(): void {
    if (this.isManualClose) return;

    console.log(`WebSocket重连尝试: ${this.path} (${this.reconnectAttempts}/${WS_CONFIG.maxReconnectAttempts})`);

    // 创建新的WebSocket连接
    this.ws = new WebSocket(this.baseUrl + this.path);
    this.setupHandlers();
  }

  // 清理重连定时器
  private clearReconnectTimer(): void {
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = undefined;
    }
  }

  // 公开的WebSocket属性和方法
  get readyState(): number {
    return this.ws.readyState;
  }

  get url(): string {
    return this.ws.url;
  }

  get protocol(): string {
    return this.ws.protocol;
  }

  get extensions(): string {
    return this.ws.extensions;
  }

  get bufferedAmount(): number {
    return this.ws.bufferedAmount;
  }

  get binaryType(): BinaryType {
    return this.ws.binaryType;
  }

  set binaryType(value: BinaryType) {
    this.ws.binaryType = value;
  }

  // 事件处理器属性
  get onopen(): ((event: Event) => void) | null {
    return this.userOnOpen;
  }

  set onopen(handler: ((event: Event) => void) | null) {
    this.userOnOpen = handler;
  }

  get onmessage(): ((event: MessageEvent) => void) | null {
    return this.userOnMessage;
  }

  set onmessage(handler: ((event: MessageEvent) => void) | null) {
    this.userOnMessage = handler;
  }

  get onclose(): ((event: CloseEvent) => void) | null {
    return this.userOnClose;
  }

  set onclose(handler: ((event: CloseEvent) => void) | null) {
    this.userOnClose = handler;
  }

  get onerror(): ((event: Event) => void) | null {
    return this.userOnError;
  }

  set onerror(handler: ((event: Event) => void) | null) {
    this.userOnError = handler;
  }

  // WebSocket方法
  send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void {
    this.ws.send(data);
  }

  close(code?: number, reason?: string): void {
    console.log(`手动关闭WebSocket: ${this.path}`);
    this.isManualClose = true;
    this.isHeartbeatTimeout = false; // 手动关闭时重置心跳超时标志
    this.stopHeartbeat();
    this.clearReconnectTimer();
    this.ws.close(code, reason);
  }

  addEventListener<K extends keyof WebSocketEventMap>(
    type: K,
    listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,
    options?: boolean | AddEventListenerOptions,
  ): void {
    this.ws.addEventListener(type, listener, options);
  }

  removeEventListener<K extends keyof WebSocketEventMap>(
    type: K,
    listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,
    options?: boolean | EventListenerOptions,
  ): void {
    this.ws.removeEventListener(type, listener, options);
  }

  dispatchEvent(event: Event): boolean {
    return this.ws.dispatchEvent(event);
  }

  // 常量
  static readonly CONNECTING = WebSocket.CONNECTING;
  static readonly OPEN = WebSocket.OPEN;
  static readonly CLOSING = WebSocket.CLOSING;
  static readonly CLOSED = WebSocket.CLOSED;

  readonly CONNECTING = WebSocket.CONNECTING;
  readonly OPEN = WebSocket.OPEN;
  readonly CLOSING = WebSocket.CLOSING;
  readonly CLOSED = WebSocket.CLOSED;
}

function create(path: string): Promise<WebSocket> {
  const baseUrl = import.meta.env.ENV_WEBSOCKET_BASE ?? '';
  const ws = new EnhancedWebSocket(path, baseUrl) as any;

  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      ws.close();
      reject(new Error('WebSocket connection timeout'));
    }, 10000); // 10秒连接超时

    ws.addEventListener('open', () => {
      clearTimeout(timeout);
      resolve(ws);
    });

    ws.addEventListener('error', (e: any) => {
      clearTimeout(timeout);
      reject(e);
    });
  });
}

export default { create };
