<script setup>import { ref, onUnmounted, watch } from 'vue';

// 定义组件的props
const props = defineProps({
  url: {
    type: String,
    default: 'ws://localhost:8805'
  },
  protocols: {
    type: Array,
    default: () => ['device-web']
  },
  autoConnect: {
    type: Boolean,
    default: true
  },
  maxReconnectAttempts: {
    type: Number,
    default: 0
  },
  initialReconnectDelay: {
    type: Number,
    default: 1000
  },
  maxReconnectDelay: {
    type: Number,
    default: 30000
  }
});

// 定义组件的emits
const emit = defineEmits([
  'connect',      // 连接成功时触发
  'disconnect',   // 断开连接时触发
  'message',      // 收到消息时触发
  'error',        // 发生错误时触发
  'status-change' // 连接状态改变时触发
]);

// 内部状态管理
const ws = ref(null);
const isConnected = ref(false);
const reconnectAttempts = ref(0);
const reconnectDelay = ref(props.initialReconnectDelay);
const reconnectTimer = ref(null);
const manualDisconnect = ref(false);
const currentUrl = ref(props.url);

// 调试日志函数
const debugLog = (...args) => {
  if (window.DEBUG) {
    console.log('[WebSocketClient]', ...args);
  }
};

// 更新连接状态并发出状态改变事件
const updateConnectionStatus = (connected) => {
  if (isConnected.value !== connected) {
    isConnected.value = connected;
    emit('status-change', connected);
    if (connected) {
      // 连接成功时发出连接事件
      emit('connect', currentUrl.value);
      // 重置重连状态
      reconnectAttempts.value = 0;
      reconnectDelay.value = props.initialReconnectDelay;
    } else {
      ws.value = null;
    }
  }
};

// 取消当前的重连尝试
const cancelReconnect = () => {
  if (reconnectTimer.value) {
    clearTimeout(reconnectTimer.value);
    reconnectTimer.value = null;
  }
};

// 智能重连策略
const reconnect = () => {
  // 如果是手动断开，不进行重连
  if (manualDisconnect.value) {
    return;
  }
  
  // 达到最大重连次数且最大重连次数不为0时，停止重连
  // 当maxReconnectAttempts为0时表示无限重试
  if (props.maxReconnectAttempts > 0 && reconnectAttempts.value >= props.maxReconnectAttempts) {
    debugLog('已达到最大重连次数');
    emit('error', '已达到最大重连次数，请手动尝试重新连接');
    return;
  }
  
  // 指数退避重连延迟
  const delay = Math.min(reconnectDelay.value * Math.pow(2, reconnectAttempts.value), props.maxReconnectDelay);
  
  // 调整日志显示：当maxReconnectAttempts为0时显示"无限重试"模式
  if (props.maxReconnectAttempts === 0) {
    debugLog(`无限重试模式：将在${Math.round(delay/1000)}秒后尝试第${reconnectAttempts.value + 1}次重连`);
  } else {
    debugLog(`将在${Math.round(delay/1000)}秒后尝试第${reconnectAttempts.value + 1}/${props.maxReconnectAttempts}次重连`);
  }
  
  reconnectTimer.value = setTimeout(() => {
    reconnectAttempts.value++;
    connect();
  }, delay);
};

// 连接WebSocket服务器
const connect = (url = null) => {
  // 如果提供了新的URL，则更新当前URL
  if (url) {
    currentUrl.value = url;
  }
  
  manualDisconnect.value = false;
  cancelReconnect();
  
  try {
    debugLog(`尝试连接到: ${currentUrl.value}`);
    
    ws.value = new WebSocket(currentUrl.value, props.protocols);
    
    // 连接成功
    ws.value.onopen = () => {
      debugLog('连接成功');
      updateConnectionStatus(true);
    };
    
    // 接收消息
    ws.value.onmessage = (event) => {
      debugLog('收到消息:', event.data);
      emit('message', event.data);
    };
    
    // 连接关闭
    ws.value.onclose = (event) => {
      debugLog(`连接关闭: 代码=${event.code}, 原因=${event.reason}`);
      updateConnectionStatus(false);
      emit('disconnect', event.code, event.reason);
      
      // 异常断开时自动重连
      if (event.code === 1006) {
        reconnect();
      } else if (!manualDisconnect.value) {
        // 非手动断开且非1006错误时也尝试重连
        reconnect();
      }
    };
    
    // 连接错误
    ws.value.onerror = (error) => {
      debugLog('WebSocket错误:', error);
      emit('error', '连接错误，请检查服务器是否运行');
      updateConnectionStatus(false);
      // 错误时也尝试重连
      if (!manualDisconnect.value) {
        reconnect();
      }
    };
  } catch (error) {
    debugLog('连接失败:', error);
    emit('error', '连接失败，请重试');
    // 连接失败也尝试重连
    if (!manualDisconnect.value) {
      reconnect();
    }
  }
};

// 断开WebSocket连接
const disconnect = () => {
  if (ws.value) {
    manualDisconnect.value = true;
    cancelReconnect();
    ws.value.close();
    updateConnectionStatus(false);
    debugLog('已断开连接');
  }
};

// 发送消息
const send = (message) => {
  if (!message || !ws.value || !isConnected.value) {
    debugLog('发送消息失败: 连接未建立或消息为空');
    return false;
  }
  
  try {
    ws.value.send(message);
    debugLog('消息发送成功:', message);
    return true;
  } catch (error) {
    debugLog('消息发送失败:', error);
    emit('error', '消息发送失败');
    return false;
  }
};

// 切换连接状态
const toggleConnection = () => {
  if (isConnected.value) {
    disconnect();
  } else {
    connect();
  }
};

// 监听props.url的变化
watch(() => props.url, (newUrl) => {
  if (newUrl && newUrl !== currentUrl.value) {
    // 如果当前已连接，则先断开连接
    if (isConnected.value) {
      disconnect();
      // 延迟重新连接，确保旧连接完全关闭
      setTimeout(() => {
        connect(newUrl);
      }, 500);
    } else {
      // 如果当前未连接，直接更新URL
      currentUrl.value = newUrl;
    }
  }
});

// 组件挂载时，如果设置了autoConnect为true，则自动连接
if (props.autoConnect) {
  connect();
}

// 组件卸载时清理资源
onUnmounted(() => {
  disconnect();
});

// 暴露方法给父组件使用
defineExpose({
  connect,
  disconnect,
  send,
  toggleConnection,
  isConnected,
  currentUrl
});
</script>

<template>
  <!-- 这个组件没有UI界面元素 -->
</template>