/**
 * 简化的WebSocket管理器
 * 专门负责WebSocket连接和消息传输，不包含打字机逻辑
 */

import { IdUtils } from "./IdUtils";
import { CallbackUtils } from "./CallbackUtils";
import { MessageUtils } from "./MessageUtils";
import { TimerUtils } from "./TimerUtils";

declare const uni: any;

type TimerHandle =
  | ReturnType<typeof setTimeout>
  | ReturnType<typeof setInterval>;

type WebSocketProtocol = string | string[];
type WebSocketMessage = Record<string, any> & {
  retryCount?: number;
  timestamp?: number;
};
type WebSocketCallback = (...args: any[]) => any;
type WebSocketLike = {
  readyState?: number;
  send?: (payload: any) => void;
  close?: (...args: any[]) => void;
  onOpen?: (callback: (event: unknown) => void) => void;
  onMessage?: (callback: (event: unknown) => void) => void;
  onClose?: (callback: (event: WebSocketCloseEvent) => void) => void;
  onError?: (callback: (error: any) => void) => void;
  onopen?: any;
  onmessage?: any;
  onclose?: any;
  onerror?: any;
};
type WebSocketCloseEvent = {
  code?: number;
  reason?: string;
};
type WebSocketManagerCallbacks = {
  onConnect?: WebSocketCallback;
  onDisconnect?: WebSocketCallback;
  onError?: WebSocketCallback;
  onMessage?: WebSocketCallback;
  getConversationId?: () => string;
  getAgentId?: () => string;
  [key: string]: WebSocketCallback | undefined;
};
type WebSocketManagerStats = {
  messagesReceived: number;
  messagesSent: number;
  messagesDropped: number;
  reconnectCount: number;
  connectionStartTime: number | null;
  lastMessageTime: number | null;
};
type WebSocketManagerOptions = {
  wsUrl?: string;
  protocols?: WebSocketProtocol;
  reconnectInterval?: number;
  maxReconnectAttempts?: number;
  heartbeatInterval?: number;
  onConnect?: WebSocketCallback;
  onOpen?: WebSocketCallback;
  onDisconnect?: WebSocketCallback;
  onClose?: WebSocketCallback;
  onError?: WebSocketCallback;
  onMessage?: WebSocketCallback;
  getConversationId?: () => string;
  getAgentId?: () => string;
};

export class WebSocketManager {
  wsUrl: string;
  protocols: WebSocketProtocol;
  reconnectInterval: number;
  maxReconnectAttempts: number;
  heartbeatInterval: number;
  ws: WebSocketLike | null;
  reconnectAttempts: number;
  isConnecting: boolean;
  connectionState: boolean;
  heartbeatTimer: TimerHandle | null;
  reconnectTimer: TimerHandle | null;
  callbacks: WebSocketManagerCallbacks;
  messageQueue: WebSocketMessage[];
  isProcessingQueue: boolean;
  stats: WebSocketManagerStats;

  constructor(options: WebSocketManagerOptions = {}) {
    // 基础配置
    console.log("WebSocketManager构造函数接收到的options:", options);
    this.wsUrl = options.wsUrl || "";
    console.log("WebSocketManager设置的wsUrl:", this.wsUrl);
    this.protocols = options.protocols || [];
    this.reconnectInterval = options.reconnectInterval || 3000;
    this.maxReconnectAttempts = options.maxReconnectAttempts || 5;
    this.heartbeatInterval = options.heartbeatInterval || 30000;

    // WebSocket 实例
    this.ws = null;
    this.reconnectAttempts = 0;
    this.isConnecting = false;
    this.connectionState = false;

    // 计时器
    this.heartbeatTimer = null;
    this.reconnectTimer = null;

    // 回调函数
    this.callbacks = {
      // 支持两套回调命名：onConnect/onDisconnect 与 onOpen/onClose（兼容调用方）
      onConnect: options.onConnect || options.onOpen || (() => {}),
      onDisconnect: options.onDisconnect || options.onClose || (() => {}),
      onError: options.onError || (() => {}),
      onMessage: options.onMessage || (() => {}),
      getConversationId: options.getConversationId || (() => ""),
      getAgentId: options.getAgentId || (() => ""),
    };

    // 消息队列
    this.messageQueue = [];
    this.isProcessingQueue = false;

    // 性能统计
    this.stats = {
      messagesReceived: 0,
      messagesSent: 0,
      messagesDropped: 0,
      reconnectCount: 0,
      connectionStartTime: null,
      lastMessageTime: null,
    };
  }

  /**
   * 安全调用回调函数
   */
  _safeCallCallback(callbackName: string, ...args: any[]): void {
    CallbackUtils.safeCall(
      this.callbacks as Record<string, (...args: any[]) => void>,
      callbackName,
      ...args,
    );
  }

  /**
   * 初始化连接
   */
  async init(wsUrl?: string): Promise<void> {
    if (wsUrl) {
      this.wsUrl = wsUrl;
    }

    if (!this.wsUrl) {
      throw new Error("WebSocket URL is required");
    }

    await this.connect();
  }

  /**
   * 建立WebSocket连接
   */
  async connect(): Promise<void> {
    if (this.isConnecting || this.connectionState) {
      console.log("WebSocket已在连接中或已连接，跳过连接");
      return;
    }

    console.log("开始建立WebSocket连接:", this.wsUrl);
    this.isConnecting = true;

    try {
      // 在小程序环境中使用 uni.connectSocket
      if (typeof uni !== "undefined" && uni.connectSocket) {
        try {
          this.ws = uni.connectSocket({
            url: this.wsUrl,
            protocols: this.protocols,
            success: () => {
              console.log("uni.connectSocket调用成功");
            },
            fail: (error: unknown) => {
              console.error("uni.connectSocket调用失败:", error);
              this.isConnecting = false;
              this.connectionState = false;
              this._safeCallCallback("onError", {
                type: "CONNECTION_ERROR",
                message: "uni.connectSocket调用失败",
                originalError: error,
              });
              this.scheduleReconnect();
              return;
            },
          });

          // 确保ws对象存在且有相应方法
          const socket = this.ws;
          if (
            socket &&
            typeof socket.onOpen === "function" &&
            typeof socket.onMessage === "function" &&
            typeof socket.onClose === "function" &&
            typeof socket.onError === "function"
          ) {
            socket.onOpen(this.handleOpen.bind(this));
            socket.onMessage(this.handleMessage.bind(this));
            socket.onClose(this.handleClose.bind(this));
            socket.onError(this.handleError.bind(this));
          } else {
            console.error("uni.connectSocket返回的对象无效");
            this.isConnecting = false;
            this.connectionState = false;
            this._safeCallCallback("onError", {
              type: "CONNECTION_ERROR",
              message: "uni.connectSocket返回的SocketTask对象无效",
              originalError: null,
            });
            this.scheduleReconnect();
            return;
          }
        } catch (error) {
          console.error("创建uni.connectSocket时发生异常:", error);
          this.isConnecting = false;
          this.connectionState = false;
          this._safeCallCallback("onError", {
            type: "CONNECTION_ERROR",
            message: "创建WebSocket连接时发生异常",
            originalError: error,
          });
          this.scheduleReconnect();
          return;
        }
      } else {
        // 在其他环境中使用标准 WebSocket
        console.log("使用标准WebSocket创建连接");
        const socket = new WebSocket(this.wsUrl, this.protocols);
        this.ws = socket;

        socket.onopen = this.handleOpen.bind(this);
        socket.onmessage = this.handleMessage.bind(this);
        socket.onclose = this.handleClose.bind(this);
        socket.onerror = this.handleError.bind(this);
      }

      console.log("WebSocket实例创建成功，等待连接...");
    } catch (error) {
      console.error("WebSocket连接创建失败:", error);
      this.isConnecting = false;
      this.connectionState = false;
      this._safeCallCallback("onError", {
        type: "CONNECTION_CREATE_ERROR",
        message: "WebSocket连接创建失败",
        originalError: error,
      });
      this.scheduleReconnect();
    }
  }

  /**
   * 连接成功处理
   */
  handleOpen(event: unknown): void {
    console.log("WebSocket连接已建立");
    this.isConnecting = false;
    this.connectionState = true;
    this.reconnectAttempts = 0;
    this.stats.connectionStartTime = Date.now();

    this.startHeartbeat();

    // 安全调用 onConnect 回调
    this._safeCallCallback("onConnect", event);

    // 处理队列中的消息
    this._processMessageQueue();
  }

  /**
   * 处理消息队列
   */
  _processMessageQueue(): void {
    while (this.messageQueue.length > 0) {
      const queuedMessage = this.messageQueue.shift();
      if (!queuedMessage) {
        continue;
      }

      // 检查重试次数
      if ((queuedMessage.retryCount ?? 0) >= 3) {
        console.warn("消息重试次数超限，丢弃消息:", queuedMessage);
        this.stats.messagesDropped++;
        continue;
      }

      queuedMessage.retryCount = (queuedMessage.retryCount || 0) + 1;
      this.sendMessage(queuedMessage);
    }
  }

  /**
   * 消息接收处理
   */
  handleMessage(event: { data?: unknown } | unknown): void {
    try {
      // 在小程序环境中，消息数据可能在 event.data 中
      const messageData = (event as { data?: unknown }).data || event;

      // 处理心跳响应和其他非JSON消息 - 在JSON解析前检查
      if (typeof messageData === "string") {
        // 处理心跳响应
        if (MessageUtils.isPongMessage(messageData)) {
          // console.log("收到心跳响应:", messageData);
          return;
        }

        // 尝试解析JSON，如果失败则忽略该消息
        const data = MessageUtils.safeParseJSON(messageData);
        if (data) {
          this.stats.messagesReceived++;
          this.stats.lastMessageTime = Date.now();
          console.log("收到WebSocket消息:", data);

          // 心跳响应 - 兼容对象格式
          if (MessageUtils.isPongMessage(data)) {
            return;
          }

          // 直接传递消息给回调处理
          this._safeCallCallback("onMessage", data);
        } else {
          console.warn("收到非JSON格式消息，已忽略:", messageData);
          return;
        }
      } else {
        // 处理对象格式的消息
        const data = messageData;
        this.stats.messagesReceived++;
        this.stats.lastMessageTime = Date.now();
        console.log("收到WebSocket消息:", data);

        // 心跳响应 - 兼容对象格式
        if (MessageUtils.isPongMessage(data)) {
          return;
        }

        // 直接传递消息给回调处理
        this._safeCallCallback("onMessage", data);
      }
    } catch (error) {
      console.error("消息处理错误:", error, "原始消息:", event);
      // 不抛出错误，避免影响其他消息处理
    }
  }

  /**
   * 连接关闭处理
   */
  handleClose(event: WebSocketCloseEvent): void {
    console.log("WebSocket连接已关闭:", event.code, event.reason);
    this.connectionState = false;
    this.isConnecting = false;

    this.stopHeartbeat();

    // 安全调用 onDisconnect 回调
    this._safeCallCallback("onDisconnect", event);

    // 非正常关闭时尝试重连
    if (
      event.code !== 1000 &&
      this.reconnectAttempts < this.maxReconnectAttempts
    ) {
      this.scheduleReconnect();
    }
  }

  /**
   * 错误处理
   */
  handleError(error: any): void {
    const errorDetails = {
      error,
      wsUrl: this.wsUrl,
      readyState: this.ws ? this.ws.readyState : "WebSocket实例不存在",
      isConnecting: this.isConnecting,
      connectionState: this.connectionState,
      reconnectAttempts: this.reconnectAttempts,
      timestamp: new Date().toISOString(),
    };

    console.error("WebSocket错误详情:", errorDetails);

    // 重置连接状态
    this.connectionState = false;
    this.isConnecting = false;

    // 构造结构化错误信息
    const structuredError = {
      type: "WEBSOCKET_ERROR",
      message: error?.message || "未知WebSocket错误",
      originalError: error,
      details: errorDetails,
    };

    // 安全调用 onError 回调
    this._safeCallCallback("onError", structuredError);

    // 如果不是正在重连中，尝试重连
    if (
      !this.reconnectTimer &&
      this.reconnectAttempts < this.maxReconnectAttempts
    ) {
      console.log("错误后尝试重连");
      this.scheduleReconnect();
    }
  }

  /**
   * 发送消息
   */
  sendMessage(message: WebSocketMessage): boolean {
    const messageData = {
      ...message,
      timestamp: Date.now(),
      retryCount:
        typeof message.retryCount === "number" ? message.retryCount : 0,
    };

    if (this.connectionState) {
      try {
        const messageStr = JSON.stringify(messageData);

        // 在小程序环境中使用不同的发送方法
        if (typeof uni !== "undefined" && this.ws && this.ws.send) {
          // uni-app 小程序环境
          this.ws.send({
            data: messageStr,
            success: () => {
              this.stats.messagesSent++;
              //console.log("消息发送成功:", messageData);
            },
            fail: (error: unknown) => {
              console.error("发送消息失败:", error);
              this._safeCallCallback("onError", error);

              // 发送失败时加入重试队列
              this.messageQueue.push(messageData);
            },
          });
        } else if (this.ws && this.ws.send) {
          // 标准 WebSocket 环境
          this.ws.send(messageStr);
          this.stats.messagesSent++;
          //console.log("消息发送成功:", messageData);
        }

        return true;
      } catch (error) {
        console.error("发送消息失败:", error);
        this._safeCallCallback("onError", error);

        // 发送失败时加入重试队列
        this.messageQueue.push(messageData);
        return false;
      }
    } else {
      // 连接未建立时加入队列
      this.messageQueue.push(messageData);
      this.connect(); // 尝试连接
      return false;
    }
  }

  /**
   * 开始心跳
   */
  startHeartbeat(): void {
    this.stopHeartbeat();

    this.heartbeatTimer = setInterval(() => {
      if (this.connectionState && this.ws) {
        try {
          // 使用标准消息格式发送心跳 (messageType=3)
          const heartbeatMessage = {
            conversationId: this.callbacks.getConversationId
              ? this.callbacks.getConversationId()
              : "",
            agentId: this.callbacks.getAgentId
              ? this.callbacks.getAgentId()
              : "",
            messageType: "3", // 心跳检测
            messageContent: "heartbeat",
            messageId: IdUtils.generateMessageId(),
          };

          this.sendMessage(heartbeatMessage);
          // console.log("心跳消息已发送:", heartbeatMessage);
        } catch (error) {
          console.error("发送心跳失败:", error);
          this.handleError(error);
        }
      }
    }, this.heartbeatInterval);
  }

  /**
   * 停止心跳
   */
  stopHeartbeat(): void {
    TimerUtils.clearTimer(this.heartbeatTimer, "interval");
    this.heartbeatTimer = null;
  }

  /**
   * 安排重连
   */
  scheduleReconnect(): void {
    // 清理之前的重连定时器
    if (this.reconnectTimer) {
      TimerUtils.clearTimer(this.reconnectTimer);
      this.reconnectTimer = null;
    }

    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.error(`达到最大重连次数(${this.maxReconnectAttempts})，停止重连`);
      this.connectionState = false;
      this.isConnecting = false;

      // 使用更温和的错误处理，避免抛出异常
      const errorInfo = {
        type: "CONNECTION_FAILED",
        message: `连接失败，已达到最大重连次数(${this.maxReconnectAttempts})`,
        attempts: this.reconnectAttempts,
        maxAttempts: this.maxReconnectAttempts,
      };

      console.warn("WebSocket连接最终失败:", errorInfo);
      this._safeCallCallback("onError", errorInfo);
      return;
    }

    this.reconnectAttempts++;
    this.stats.reconnectCount++;

    // 使用指数退避策略
    const backoffDelay = Math.min(
      this.reconnectInterval * Math.pow(1.5, this.reconnectAttempts - 1),
      30000, // 最大延迟30秒
    );

    console.log(
      `${backoffDelay}ms后进行第${this.reconnectAttempts}/${this.maxReconnectAttempts}次重连`,
    );

    this.reconnectTimer = setTimeout(() => {
      this.reconnectTimer = null;
      this.connect().catch((error) => {
        console.error("重连过程中发生错误:", error);
        // 继续尝试重连
        this.scheduleReconnect();
      });
    }, backoffDelay);
  }

  /**
   * 重置连接状态
   */
  resetConnectionState(): void {
    this.connectionState = false;
    this.isConnecting = false;
    this.reconnectAttempts = 0;

    // 清理定时器
    this.stopHeartbeat();
    if (this.reconnectTimer) {
      TimerUtils.clearTimer(this.reconnectTimer);
      this.reconnectTimer = null;
    }

    console.log("连接状态已重置");
  }

  /**
   * 检查是否已连接
   */
  isConnected(): boolean {
    return Boolean(
      this.connectionState &&
      this.ws &&
      (this.ws.readyState === 1 ||
        (typeof WebSocket !== "undefined" &&
          this.ws.readyState === WebSocket.OPEN))
    );
  }

  /**
   * 手动重连
   */
  async reconnect(): Promise<boolean> {
    console.log("手动触发重连");

    // 先关闭现有连接
    this.close();

    // 重置连接状态
    this.resetConnectionState();

    // 重新连接
    try {
      await this.connect();
      return true;
    } catch (error) {
      console.error("手动重连失败:", error);
      return false;
    }
  }

  /**
   * 获取连接状态
   */
  getConnectionState() {
    return {
      isConnected: this.isConnected(),
      readyState: this.ws ? this.ws.readyState : -1,
      reconnectAttempts: this.reconnectAttempts,
      maxReconnectAttempts: this.maxReconnectAttempts,
      isConnecting: this.isConnecting,
      hasReconnectTimer: !!this.reconnectTimer,
    };
  }

  /**
   * 获取统计信息
   */
  getStats() {
    const now = Date.now();
    const connectionTime = this.stats.connectionStartTime
      ? now - this.stats.connectionStartTime
      : 0;

    return {
      ...this.stats,
      connectionTime,
      queueLength: this.messageQueue.length,
      isConnected: this.connectionState,
    };
  }

  /**
   * 重置统计信息
   */
  resetStats(): void {
    this.stats = {
      messagesReceived: 0,
      messagesSent: 0,
      messagesDropped: 0,
      reconnectCount: 0,
      connectionStartTime: Date.now(),
      lastMessageTime: null,
    };
    console.log("统计信息已重置");
  }

  /**
   * 关闭连接
   */
  close(): void {
    this.stopHeartbeat();
    this.resetConnectionState();

    // 清理重连定时器
    TimerUtils.clearTimer(this.reconnectTimer);
    this.reconnectTimer = null;

    if (this.ws) {
      // 在小程序环境中使用不同的关闭方法
      if (typeof uni !== "undefined" && this.ws.close) {
        // uni-app 小程序环境
        this.ws.close({
          code: 1000,
          reason: "正常关闭",
          success: () => {
            console.log("WebSocket连接已关闭");
          },
          fail: (error: unknown) => {
            console.error("关闭WebSocket连接失败:", error);
          },
        });
      } else if (this.ws.close) {
        // 标准 WebSocket 环境
        this.ws.close(1000, "正常关闭");
      }
      this.ws = null;
    }

    this.connectionState = false;
    this.isConnecting = false;
    this.messageQueue = [];
  }

  /**
   * 销毁实例
   */
  destroy(): void {
    // 输出最终统计信息
    console.log("WebSocketManager销毁前统计:", this.getStats());

    this.close();
    this.callbacks = {};

    console.log("WebSocketManager实例已销毁");
  }
}

export default WebSocketManager;
