<template>
  <view class="test-page">
    <view class="test-header">
      <text class="title">WebSocket 测试工具</text>
      <text class="subtitle">实时测试 WebSocket 连接和消息</text>
    </view>

    <!-- 连接状态 -->
    <view class="status-card">
      <view class="status-item">
        <text class="label">连接状态：</text>
        <text :class="['value', connectionStatus.class]">{{ connectionStatus.text }}</text>
      </view>
      <view class="status-item">
        <text class="label">队列消息：</text>
        <text class="value">{{ queueLength }} 条</text>
      </view>
      <view class="status-item">
        <text class="label">重连次数：</text>
        <text class="value">{{ reconnectAttempts }} 次</text>
      </view>
    </view>

    <!-- 连接控制 -->
    <view class="control-card">
      <view class="control-title">连接控制</view>
      <input
        class="url-input"
        v-model="wsUrl"
        placeholder="输入 WebSocket 地址"
      />
      <view class="button-group">
        <button class="btn btn-primary" @click="handleConnect" :disabled="isConnected">
          连接
        </button>
        <button class="btn btn-danger" @click="handleDisconnect" :disabled="!isConnected">
          断开
        </button>
      </view>
    </view>

    <!-- 消息发送 -->
    <view class="message-card">
      <view class="control-title">发送消息</view>
      <textarea
        class="message-input"
        v-model="messageToSend"
        placeholder="输入消息内容（JSON 格式）"
        :rows="5"
      ></textarea>
      <view class="button-group">
        <button class="btn btn-success" @click="handleSendMessage" :disabled="!isConnected">
          发送消息
        </button>
        <button class="btn btn-secondary" @click="handleSendPing" :disabled="!isConnected">
          发送心跳
        </button>
      </view>
    </view>

    <!-- 快速测试 -->
    <view class="quick-test-card">
      <view class="control-title">快速测试</view>
      <view class="button-group">
        <button class="btn btn-info" @click="testEcho">
          Echo 服务测试
        </button>
        <button class="btn btn-info" @click="testLocalServer">
          本地服务器测试
        </button>
      </view>
    </view>

    <!-- 日志显示 -->
    <view class="log-card">
      <view class="log-header">
        <text class="control-title">日志 ({{ logs.length }})</text>
        <button class="btn-clear" @click="clearLogs">清空</button>
      </view>
      <scroll-view class="log-content" scroll-y>
        <view
          v-for="(log, index) in logs"
          :key="index"
          :class="['log-item', `log-${log.type}`]"
        >
          <text class="log-time">{{ log.time }}</text>
          <text class="log-type">{{ log.typeText }}</text>
          <text class="log-message">{{ log.message }}</text>
        </view>
        <view v-if="logs.length === 0" class="empty-log">
          暂无日志
        </view>
      </scroll-view>
    </view>
  </view>
</template>

<script>
import wsManager from '@/utils/websocket-manager.js'

export default {
  name: 'WebSocketTest',
  data() {
    return {
      // WebSocket URL
      wsUrl: 'wss://echo.websocket.org',
      
      // 连接状态
      isConnected: false,
      reconnectAttempts: 0,
      queueLength: 0,
      
      // 消息
      messageToSend: JSON.stringify({
        type: 'test',
        content: 'Hello WebSocket!',
        timestamp: Date.now()
      }, null, 2),
      
      // 日志
      logs: [],
      
      // 计时器
      startTime: 0
    }
  },
  
  computed: {
    connectionStatus() {
      if (this.isConnected) {
        return { text: '已连接', class: 'status-connected' }
      } else if (this.reconnectAttempts > 0) {
        return { text: '重连中...', class: 'status-reconnecting' }
      } else {
        return { text: '未连接', class: 'status-disconnected' }
      }
    }
  },
  
  onLoad() {
    this.setupEventListeners()
    this.addLog('info', '测试工具已加载')
  },
  
  onUnload() {
    // 清理事件监听
    wsManager.off('open', this.handleOpen)
    wsManager.off('close', this.handleClose)
    wsManager.off('error', this.handleError)
    wsManager.off('message', this.handleMessage)
    wsManager.off('reconnect', this.handleReconnect)
  },
  
  methods: {
    // 设置事件监听
    setupEventListeners() {
      this.handleOpen = () => {
        this.isConnected = true
        this.reconnectAttempts = 0
        const duration = Date.now() - this.startTime
        this.addLog('success', `连接成功 (耗时 ${duration}ms)`)
      }
      
      this.handleClose = (res) => {
        this.isConnected = false
        this.addLog('warning', `连接关闭 (code: ${res.code})`)
      }
      
      this.handleError = (err) => {
        this.addLog('error', `连接错误: ${JSON.stringify(err)}`)
      }
      
      this.handleMessage = (data) => {
        this.addLog('message', `收到消息: ${JSON.stringify(data, null, 2)}`)
      }
      
      this.handleReconnect = (attempts) => {
        this.reconnectAttempts = attempts
        this.addLog('info', `正在重连 (第 ${attempts} 次)`)
      }
      
      wsManager.on('open', this.handleOpen)
      wsManager.on('close', this.handleClose)
      wsManager.on('error', this.handleError)
      wsManager.on('message', this.handleMessage)
      wsManager.on('reconnect', this.handleReconnect)
    },
    
    // 连接
    handleConnect() {
      if (!this.wsUrl) {
        uni.showToast({ title: '请输入 WebSocket 地址', icon: 'none' })
        return
      }
      
      this.addLog('info', `开始连接: ${this.wsUrl}`)
      this.startTime = Date.now()
      
      wsManager.connect(this.wsUrl, {
        reconnectInterval: 3000,
        maxReconnectAttempts: 5,
        heartbeatInterval: 30000
      })
      
      this.updateState()
    },
    
    // 断开连接
    handleDisconnect() {
      this.addLog('info', '手动断开连接')
      wsManager.close(true)
      this.isConnected = false
      this.reconnectAttempts = 0
    },
    
    // 发送消息
    handleSendMessage() {
      try {
        const message = JSON.parse(this.messageToSend)
        this.addLog('send', `发送消息: ${JSON.stringify(message)}`)
        wsManager.send(message)
      } catch (e) {
        this.addLog('error', `消息格式错误: ${e.message}`)
        uni.showToast({ title: 'JSON 格式错误', icon: 'none' })
      }
    },
    
    // 发送心跳
    handleSendPing() {
      const ping = {
        type: 'ping',
        timestamp: Date.now()
      }
      this.addLog('send', `发送心跳: ${JSON.stringify(ping)}`)
      wsManager.send(ping)
    },
    
    // Echo 服务测试
    testEcho() {
      this.wsUrl = 'wss://echo.websocket.org'
      this.messageToSend = JSON.stringify({
        type: 'test',
        content: 'Echo 测试消息',
        timestamp: Date.now()
      }, null, 2)
      
      this.addLog('info', '开始 Echo 服务测试')
      uni.showToast({ title: '点击"连接"开始测试', icon: 'none' })
    },
    
    // 本地服务器测试
    testLocalServer() {
      this.wsUrl = 'ws://localhost:8073/ws/chat?token=test-token'
      this.messageToSend = JSON.stringify({
        type: 'message',
        fromUserId: 'test_user',
        toUserId: 'admin',
        content: '本地服务器测试',
        timestamp: Date.now()
      }, null, 2)
      
      this.addLog('info', '开始本地服务器测试')
      uni.showToast({ title: '点击"连接"开始测试', icon: 'none' })
    },
    
    // 更新状态
    updateState() {
      const state = wsManager.getState()
      this.isConnected = state.isConnected
      this.reconnectAttempts = state.reconnectAttempts
      this.queueLength = state.queueLength
    },
    
    // 添加日志
    addLog(type, message) {
      const typeMap = {
        info: 'ℹ️ 信息',
        success: '✅ 成功',
        warning: '⚠️ 警告',
        error: '❌ 错误',
        send: '📤 发送',
        message: '📩 接收'
      }
      
      const now = new Date()
      const time = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`
      
      this.logs.unshift({
        type,
        typeText: typeMap[type] || type,
        message,
        time
      })
      
      // 最多保留 100 条日志
      if (this.logs.length > 100) {
        this.logs.pop()
      }
    },
    
    // 清空日志
    clearLogs() {
      this.logs = []
      this.addLog('info', '日志已清空')
    }
  }
}
</script>

<style scoped>
.test-page {
  padding: 20rpx;
  background-color: #f5f6fa;
  min-height: 100vh;
}

.test-header {
  text-align: center;
  padding: 40rpx 0;
}

.title {
  font-size: 36rpx;
  font-weight: bold;
  color: #333;
  display: block;
}

.subtitle {
  font-size: 24rpx;
  color: #999;
  margin-top: 10rpx;
  display: block;
}

.status-card,
.control-card,
.message-card,
.quick-test-card,
.log-card {
  background: #fff;
  border-radius: 16rpx;
  padding: 30rpx;
  margin-bottom: 20rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
}

.status-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20rpx 0;
  border-bottom: 1rpx solid #f0f0f0;
}

.status-item:last-child {
  border-bottom: none;
}

.label {
  font-size: 28rpx;
  color: #666;
}

.value {
  font-size: 28rpx;
  font-weight: 500;
  color: #333;
}

.status-connected {
  color: #52c41a;
}

.status-reconnecting {
  color: #faad14;
}

.status-disconnected {
  color: #999;
}

.control-title {
  font-size: 30rpx;
  font-weight: 500;
  color: #333;
  margin-bottom: 20rpx;
}

.url-input,
.message-input {
  width: 100%;
  padding: 20rpx;
  border: 1rpx solid #d9d9d9;
  border-radius: 8rpx;
  font-size: 26rpx;
  margin-bottom: 20rpx;
  box-sizing: border-box;
}

.message-input {
  min-height: 200rpx;
  font-family: 'Courier New', monospace;
}

.button-group {
  display: flex;
  gap: 20rpx;
}

.btn {
  flex: 1;
  height: 80rpx;
  line-height: 80rpx;
  text-align: center;
  border-radius: 8rpx;
  font-size: 28rpx;
  border: none;
}

.btn-primary {
  background: #1890ff;
  color: #fff;
}

.btn-danger {
  background: #ff4d4f;
  color: #fff;
}

.btn-success {
  background: #52c41a;
  color: #fff;
}

.btn-secondary {
  background: #d9d9d9;
  color: #666;
}

.btn-info {
  background: #722ed1;
  color: #fff;
}

.btn:disabled {
  opacity: 0.5;
}

.log-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20rpx;
}

.btn-clear {
  padding: 10rpx 20rpx;
  background: #f0f0f0;
  border: none;
  border-radius: 8rpx;
  font-size: 24rpx;
  color: #666;
}

.log-content {
  height: 600rpx;
  border: 1rpx solid #f0f0f0;
  border-radius: 8rpx;
  padding: 20rpx;
}

.log-item {
  padding: 20rpx;
  margin-bottom: 10rpx;
  border-radius: 8rpx;
  font-size: 24rpx;
  line-height: 1.6;
  word-break: break-all;
}

.log-info {
  background: #e6f7ff;
  border-left: 4rpx solid #1890ff;
}

.log-success {
  background: #f6ffed;
  border-left: 4rpx solid #52c41a;
}

.log-warning {
  background: #fffbe6;
  border-left: 4rpx solid #faad14;
}

.log-error {
  background: #fff2f0;
  border-left: 4rpx solid #ff4d4f;
}

.log-send {
  background: #f9f0ff;
  border-left: 4rpx solid #722ed1;
}

.log-message {
  background: #fff0f6;
  border-left: 4rpx solid #eb2f96;
}

.log-time {
  color: #999;
  margin-right: 20rpx;
}

.log-type {
  font-weight: 500;
  margin-right: 20rpx;
}

.log-message {
  color: #333;
}

.empty-log {
  text-align: center;
  padding: 100rpx 0;
  color: #999;
  font-size: 28rpx;
}
</style>

