/**
 * 连接状态管理器
 * 
 * 提供连接状态的集中管理，包括：
 * - 6种连接状态管理（IDLE/CONNECTING/CONNECTED/RECONNECTING/DISCONNECTED/ERROR）
 * - 状态转换逻辑验证
 * - 状态订阅机制（监听器模式）
 * - 重连次数和最后连接时间跟踪
 * - 单例实例提供
 */

import {
  ConnectionState,
  ConnectionStateInfo,
  ConnectionStateListener,
  ReconnectConfig,
  StateTransitions,
  DEFAULT_STATE_TRANSITIONS,
  DEFAULT_RECONNECT_CONFIG,
  getStateDescription,
} from './types';

/**
 * 连接状态管理器类
 * 
 * 管理连接状态的生命周期，提供状态转换、订阅和状态信息查询功能。
 * 使用单例模式确保全局唯一实例。
 */
export class ConnectionStateManager {
  /** 当前连接状态 */
  private state: ConnectionState = ConnectionState.IDLE;
  /** 上一次状态 */
  private previousState: ConnectionState | null = null;
  /** 状态变更监听器集合 */
  private listeners: Set<ConnectionStateListener> = new Set();
  /** 当前重连次数 */
  private reconnectAttempts = 0;
  /** 最后成功连接时间 */
  private lastConnectedTime: number | null = null;
  /** 状态变更时间戳 */
  private lastStateChangeTime = Date.now();
  /** 当前错误信息 */
  private currentError: Error | null = null;
  /** 重连配置 */
  private reconnectConfig: ReconnectConfig;
  /** 状态转换规则 */
  private stateTransitions: StateTransitions;

  /**
   * 创建连接状态管理器实例
   * @param config 可选的重连配置
   * @param transitions 可选的状态转换规则
   */
  constructor(
    config: Partial<ReconnectConfig> = {},
    transitions: StateTransitions = DEFAULT_STATE_TRANSITIONS
  ) {
    this.reconnectConfig = { ...DEFAULT_RECONNECT_CONFIG, ...config };
    this.stateTransitions = transitions;
  }

  /**
   * 获取当前状态信息
   * @returns 完整的状态信息对象
   */
  getState(): ConnectionStateInfo {
    return {
      state: this.state,
      timestamp: this.lastStateChangeTime,
      error: this.currentError || undefined,
      reconnectAttempts: this.reconnectAttempts,
      lastConnectedAt: this.lastConnectedTime,
      description: this.getStatusDescription(),
    };
  }

  /**
   * 获取当前原始状态
   * @returns 当前连接状态枚举值
   */
  getRawState(): ConnectionState {
    return this.state;
  }

  /**
   * 获取上一次状态
   * @returns 上一次的连接状态，如果没有则为 null
   */
  getPreviousState(): ConnectionState | null {
    return this.previousState;
  }

  /**
   * 设置新状态
   * @param newState 目标状态
   * @param error 可选的错误信息
   * @returns 是否成功转换状态
   */
  setState(newState: ConnectionState, error?: Error): boolean {
    // 检查状态转换是否合法
    if (!this.canTransitionTo(newState)) {
      console.warn(
        `[ConnectionStateManager] 非法状态转换: ${this.state} -> ${newState}`
      );
      return false;
    }

    // 保存当前状态为上一状态
    this.previousState = this.state;
    this.state = newState;
    this.lastStateChangeTime = Date.now();

    // 更新错误信息
    if (error) {
      this.currentError = error;
    } else if (newState !== ConnectionState.ERROR) {
      this.currentError = null;
    }

    // 更新连接时间
    if (newState === ConnectionState.CONNECTED) {
      this.lastConnectedTime = Date.now();
      this.reconnectAttempts = 0;
    }

    // 通知监听器
    this.notifyListeners();

    return true;
  }

  /**
   * 检查是否可以转换到目标状态
   * @param targetState 目标状态
   * @returns 是否可以转换
   */
  canTransitionTo(targetState: ConnectionState): boolean {
    // 相同状态，允许（刷新状态）
    if (this.state === targetState) {
      return true;
    }

    const allowedTransitions = this.stateTransitions[this.state];
    if (!allowedTransitions) {
      return false;
    }

    return allowedTransitions.includes(targetState);
  }

  /**
   * 订阅状态变更
   * @param listener 状态变更监听器
   * @returns 取消订阅函数
   */
  subscribe(listener: ConnectionStateListener): () => void {
    this.listeners.add(listener);

    // 立即通知一次当前状态
    listener(this.getState(), null);

    // 返回取消订阅函数
    return () => {
      this.listeners.delete(listener);
    };
  }

  /**
   * 获取当前监听器数量
   * @returns 监听器数量
   */
  getListenerCount(): number {
    return this.listeners.size;
  }

  /**
   * 重置重连次数
   */
  resetReconnectAttempts(): void {
    this.reconnectAttempts = 0;
  }

  /**
   * 增加重连次数
   * @returns 增加后的重连次数
   */
  incrementReconnectAttempts(): number {
    this.reconnectAttempts++;
    return this.reconnectAttempts;
  }

  /**
   * 获取当前重连次数
   * @returns 当前重连次数
   */
  getReconnectAttempts(): number {
    return this.reconnectAttempts;
  }

  /**
   * 获取最大重连次数
   * @returns 最大重连次数
   */
  getMaxReconnectAttempts(): number {
    return this.reconnectConfig.maxReconnectAttempts;
  }

  /**
   * 获取最后连接时间
   * @returns 最后成功连接的时间戳，如果没有则为 null
   */
  getLastConnectedTime(): number | null {
    return this.lastConnectedTime;
  }

  /**
   * 获取当前错误信息
   * @returns 当前的错误信息，如果没有则为 null
   */
  getCurrentError(): Error | null {
    return this.currentError;
  }

  /**
   * 检查是否已连接
   * @returns 是否处于 CONNECTED 状态
   */
  isConnected(): boolean {
    return this.state === ConnectionState.CONNECTED;
  }

  /**
   * 检查是否正在连接
   * @returns 是否处于 CONNECTING 或 RECONNECTING 状态
   */
  isConnecting(): boolean {
    return this.state === ConnectionState.CONNECTING || this.state === ConnectionState.RECONNECTING;
  }

  /**
   * 获取状态描述
   * @returns 当前状态的描述字符串
   */
  getStatusDescription(): string {
    return getStateDescription(
      this.state,
      this.reconnectAttempts,
      this.reconnectConfig.maxReconnectAttempts
    );
  }

  /**
   * 通知所有监听器状态变更
   * @private
   */
  private notifyListeners(): void {
    const stateInfo = this.getState();
    const previousInfo = this.previousState !== null 
      ? { ...stateInfo, state: this.previousState } as ConnectionStateInfo
      : null;

    this.listeners.forEach((listener) => {
      try {
        listener(stateInfo, previousInfo);
      } catch (error) {
        console.error('[ConnectionStateManager] 监听器执行失败:', error);
      }
    });
  }

  /**
   * 销毁状态管理器
   * 清除所有监听器和状态
   */
  destroy(): void {
    this.listeners.clear();
    this.state = ConnectionState.IDLE;
    this.previousState = null;
    this.reconnectAttempts = 0;
    this.currentError = null;
  }
}

/**
 * 默认单例实例
 */
export const connectionStateManager = new ConnectionStateManager();

export default connectionStateManager;
