/**
 * WebSocket OpenAPI 文档控制器
 * 
 * 功能描述：
 * - 专门用于在OpenAPI/Swagger中展示WebSocket接口
 * - 通过REST API的方式描述WebSocket的消息格式和交互流程
 * - 提供WebSocket连接信息和测试工具推荐
 * 
 * 架构定位：
 * - 层级：Gateway层（网关层）
 * - 职责：HTTP协议处理、OpenAPI文档暴露
 * - 依赖：无业务逻辑依赖，纯文档展示
 * 
 * 职责分离：
 * - 文档展示：在Swagger中展示WebSocket消息格式
 * - 连接信息：提供WebSocket连接配置和认证信息
 * - 消息流程：展示WebSocket消息交互流程
 * - 测试工具：提供测试工具推荐和示例代码
 * 
 * 最近修改：
 * - 2026-01-14: 架构优化 - 从Business层迁移到Gateway层，符合四层架构规范 (修改者: moyin)
 * - 2026-01-14: 代码规范优化 - 完善文件头注释和职责分离描述 (修改者: moyin)
 * - 2026-01-09: 功能新增 - 初始创建WebSocket OpenAPI文档控制器 (修改者: moyin)
 * 
 * @author moyin
 * @version 2.0.0
 * @since 2026-01-09
 * @lastModified 2026-01-14
 */

import { Controller, Get, Post, Body } from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiProperty,
  ApiExtraModels,
} from '@nestjs/swagger';

// WebSocket 消息格式 DTO
class WebSocketLoginRequest {
  @ApiProperty({
    description: '消息类型',
    example: 'login',
    enum: ['login']
  })
  type: string;

  @ApiProperty({
    description: 'JWT认证令牌',
    example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
  })
  token: string;
}

class WebSocketLoginSuccessResponse {
  @ApiProperty({
    description: '响应类型',
    example: 'login_success'
  })
  t: string;

  @ApiProperty({
    description: '会话ID',
    example: '89aff162-52d9-484e-9a35-036ba63a2280'
  })
  sessionId: string;

  @ApiProperty({
    description: '用户ID',
    example: 'user_123'
  })
  userId: string;

  @ApiProperty({
    description: '用户名',
    example: 'Player_123'
  })
  username: string;

  @ApiProperty({
    description: '当前地图',
    example: 'whale_port'
  })
  currentMap: string;
}

class WebSocketChatRequest {
  @ApiProperty({
    description: '消息类型',
    example: 'chat',
    enum: ['chat']
  })
  t: string;

  @ApiProperty({
    description: '消息内容',
    example: '大家好！我刚进入游戏',
    maxLength: 1000
  })
  content: string;

  @ApiProperty({
    description: '消息范围',
    example: 'local',
    enum: ['local', 'global']
  })
  scope: string;
}

class WebSocketChatResponse {
  @ApiProperty({
    description: '响应类型',
    example: 'chat_render'
  })
  t: string;

  @ApiProperty({
    description: '发送者用户名',
    example: 'Player_456'
  })
  from: string;

  @ApiProperty({
    description: '消息内容',
    example: '欢迎新玩家！'
  })
  txt: string;

  @ApiProperty({
    description: '是否显示气泡',
    example: true
  })
  bubble: boolean;

  @ApiProperty({
    description: '消息范围',
    example: 'local'
  })
  scope: string;

  @ApiProperty({
    description: '地图ID（本地消息时）',
    example: 'whale_port',
    required: false
  })
  mapId?: string;
}

class WebSocketPositionRequest {
  @ApiProperty({
    description: '消息类型',
    example: 'position'
  })
  t: string;

  @ApiProperty({
    description: 'X坐标',
    example: 150
  })
  x: number;

  @ApiProperty({
    description: 'Y坐标',
    example: 400
  })
  y: number;

  @ApiProperty({
    description: '地图ID',
    example: 'whale_port'
  })
  mapId: string;
}

class WebSocketErrorResponse {
  @ApiProperty({
    description: '错误类型',
    example: 'error'
  })
  type: string;

  @ApiProperty({
    description: '错误消息',
    example: '请先登录'
  })
  message: string;
}

@ApiTags('websocket')
@ApiExtraModels(
  WebSocketLoginRequest,
  WebSocketLoginSuccessResponse,
  WebSocketChatRequest,
  WebSocketChatResponse,
  WebSocketPositionRequest,
  WebSocketErrorResponse
)
@Controller('websocket-api')
export class WebSocketOpenApiController {

  @Get('connection-info')
  @ApiOperation({
    summary: 'WebSocket 连接信息',
    description: `
获取WebSocket连接的基本信息和配置

**连接地址**: \`wss://whaletownend.xinghangee.icu/game\`

**协议**: 原生WebSocket (非Socket.IO)

**认证**: 需要JWT Token

**架构更新**: 
- ✅ 已从Socket.IO迁移到原生WebSocket
- ✅ 统一使用 /game 路径
- ✅ 支持地图房间管理
- ✅ 实现消息广播机制

**快速测试**: 
- 🧪 [WebSocket 测试页面](/websocket-test?from=api-docs) - 交互式测试工具
- 📚 [完整 API 文档](/api-docs) - 返回 Swagger 文档
    `
  })
  @ApiResponse({
    status: 200,
    description: 'WebSocket连接配置信息',
    schema: {
      type: 'object',
      properties: {
        url: {
          type: 'string',
          example: 'wss://whaletownend.xinghangee.icu/game',
          description: 'WebSocket服务器地址'
        },
        protocol: {
          type: 'string',
          example: 'native-websocket',
          description: '使用原生WebSocket协议'
        },
        authentication: {
          type: 'object',
          properties: {
            required: { type: 'boolean', example: true },
            method: { type: 'string', example: 'JWT Token' },
            tokenFormat: {
              type: 'object',
              properties: {
                issuer: { type: 'string', example: 'whale-town' },
                audience: { type: 'string', example: 'whale-town-users' },
                type: { type: 'string', example: 'access' }
              }
            }
          }
        },
        supportedMaps: {
          type: 'array',
          items: { type: 'string' },
          example: ['whale_port', 'pumpkin_valley', 'novice_village']
        }
      }
    }
  })
  getConnectionInfo() {
    return {
      url: 'wss://whaletownend.xinghangee.icu/game',
      protocol: 'native-websocket',
      path: '/game',
      port: {
        development: 3001,
        production: 'via_nginx_proxy'
      },
      authentication: {
        required: true,
        method: 'JWT Token',
        tokenFormat: {
          issuer: 'whale-town',
          audience: 'whale-town-users',
          type: 'access',
          requiredFields: ['sub', 'username', 'email', 'role']
        }
      },
      supportedMaps: [
        'whale_port',
        'pumpkin_valley', 
        'novice_village'
      ],
      features: [
        '实时聊天',
        '位置同步',
        '地图房间管理',
        '消息广播',
        '连接状态监控',
        '自动重连支持'
      ],
      messageTypes: {
        clientToServer: [
          {
            type: 'login',
            description: '用户登录认证',
            required: ['type', 'token']
          },
          {
            type: 'chat',
            description: '发送聊天消息',
            required: ['t', 'content', 'scope']
          },
          {
            type: 'position',
            description: '更新位置信息',
            required: ['t', 'x', 'y', 'mapId']
          }
        ],
        serverToClient: [
          {
            type: 'connected',
            description: '连接确认'
          },
          {
            type: 'login_success',
            description: '登录成功'
          },
          {
            type: 'login_error',
            description: '登录失败'
          },
          {
            type: 'chat_render',
            description: '接收聊天消息'
          },
          {
            type: 'position_update',
            description: '位置更新广播'
          },
          {
            type: 'error',
            description: '通用错误消息'
          }
        ]
      },
      connectionLimits: {
        maxConnections: 1000,
        sessionTimeout: 1800, // 30分钟
        heartbeatInterval: 30000 // 30秒
      }
    };
  }

  @Post('login')
  @ApiOperation({
    summary: '用户登录 (WebSocket消息格式)',
    description: `
**注意**: 这不是真实的REST API端点，而是WebSocket消息格式的文档展示

通过WebSocket发送此格式的消息来进行用户登录认证

**WebSocket连接后发送**:
\`\`\`json
{
  "type": "login",
  "token": "your_jwt_token_here"
}
\`\`\`

**成功响应**:
\`\`\`json
{
  "t": "login_success",
  "sessionId": "uuid",
  "userId": "user_id",
  "username": "username",
  "currentMap": "whale_port"
}
\`\`\`
    `
  })
  @ApiResponse({
    status: 200,
    description: '登录成功响应格式',
    type: WebSocketLoginSuccessResponse
  })
  @ApiResponse({
    status: 400,
    description: '登录失败响应格式',
    schema: {
      type: 'object',
      properties: {
        t: { type: 'string', example: 'login_error' },
        message: { type: 'string', example: 'Token验证失败' }
      }
    }
  })
  websocketLogin(@Body() loginRequest: WebSocketLoginRequest) {
    // 这个方法不会被实际调用，仅用于文档展示
    return {
      note: '这是WebSocket消息格式文档，请通过WebSocket连接发送消息',
      websocketUrl: 'wss://whaletownend.xinghangee.icu/game',
      messageFormat: loginRequest
    };
  }

  @Post('chat')
  @ApiOperation({
    summary: '发送聊天消息 (WebSocket消息格式)',
    description: `
**注意**: 这不是真实的REST API端点，而是WebSocket消息格式的文档展示

通过WebSocket发送聊天消息的格式

**发送消息**:
\`\`\`json
{
  "t": "chat",
  "content": "消息内容",
  "scope": "local"
}
\`\`\`

**接收消息**:
\`\`\`json
{
  "t": "chat_render",
  "from": "发送者",
  "txt": "消息内容",
  "bubble": true,
  "scope": "local",
  "mapId": "whale_port"
}
\`\`\`

**消息范围说明**:
- \`local\`: 仅当前地图的玩家可见
- \`global\`: 所有在线玩家可见
    `
  })
  @ApiResponse({
    status: 200,
    description: '聊天消息广播格式',
    type: WebSocketChatResponse
  })
  @ApiResponse({
    status: 400,
    description: '发送失败响应',
    schema: {
      type: 'object',
      properties: {
        t: { type: 'string', example: 'chat_error' },
        message: { type: 'string', example: '消息内容不能为空' }
      }
    }
  })
  websocketChat(@Body() chatRequest: WebSocketChatRequest) {
    return {
      note: '这是WebSocket消息格式文档，请通过WebSocket连接发送消息',
      websocketUrl: 'wss://whaletownend.xinghangee.icu/game',
      messageFormat: chatRequest
    };
  }

  @Post('position')
  @ApiOperation({
    summary: '位置更新 (WebSocket消息格式)',
    description: `
**注意**: 这不是真实的REST API端点，而是WebSocket消息格式的文档展示

更新玩家位置信息，支持地图切换

**发送格式**:
\`\`\`json
{
  "t": "position",
  "x": 150,
  "y": 400,
  "mapId": "whale_port"
}
\`\`\`

**功能说明**:
- 自动处理地图房间切换
- 向同地图其他玩家广播位置更新
- 支持实时位置同步
    `
  })
  @ApiResponse({
    status: 200,
    description: '位置更新成功，无特定响应消息'
  })
  websocketPosition(@Body() positionRequest: WebSocketPositionRequest) {
    return {
      note: '这是WebSocket消息格式文档，请通过WebSocket连接发送消息',
      websocketUrl: 'wss://whaletownend.xinghangee.icu/game',
      messageFormat: positionRequest
    };
  }

  @Get('message-flow')
  @ApiOperation({
    summary: 'WebSocket 消息流程图',
    description: '展示WebSocket连接和消息交互的完整流程'
  })
  @ApiResponse({
    status: 200,
    description: 'WebSocket交互流程',
    schema: {
      type: 'object',
      properties: {
        connectionFlow: {
          type: 'array',
          items: { type: 'string' },
          example: [
            '1. 建立WebSocket连接到 wss://whaletownend.xinghangee.icu/game',
            '2. 发送login消息进行认证',
            '3. 接收login_success确认',
            '4. 发送chat/position消息进行交互',
            '5. 接收其他玩家的消息广播'
          ]
        }
      }
    }
  })
  getMessageFlow() {
    return {
      connectionFlow: [
        '1. 建立WebSocket连接到 wss://whaletownend.xinghangee.icu/game',
        '2. 发送login消息进行认证',
        '3. 接收login_success确认',
        '4. 发送chat/position消息进行交互',
        '5. 接收其他玩家的消息广播'
      ],
      messageTypes: {
        clientToServer: [
          'login - 用户登录认证',
          'chat - 发送聊天消息',
          'position - 更新位置信息'
        ],
        serverToClient: [
          'connected - 连接确认',
          'login_success/login_error - 登录结果',
          'chat_sent/chat_error - 消息发送结果',
          'chat_render - 接收聊天消息',
          'position_update - 位置更新广播',
          'error - 通用错误消息'
        ]
      },
      exampleSession: {
        step1: {
          action: '建立连接',
          client: 'new WebSocket("wss://whaletownend.xinghangee.icu/game")',
          server: '{"type":"connected","message":"连接成功","socketId":"ws_123"}'
        },
        step2: {
          action: '用户登录',
          client: '{"type":"login","token":"jwt_token"}',
          server: '{"t":"login_success","sessionId":"uuid","userId":"user_123","username":"Player","currentMap":"whale_port"}'
        },
        step3: {
          action: '发送消息',
          client: '{"t":"chat","content":"Hello!","scope":"local"}',
          server: '{"t":"chat_sent","messageId":137,"message":"消息发送成功"}'
        },
        step4: {
          action: '接收广播',
          server: '{"t":"chat_render","from":"Player","txt":"Hello!","bubble":true,"scope":"local","mapId":"whale_port"}'
        }
      }
    };
  }

  @Get('testing-tools')
  @ApiOperation({
    summary: 'WebSocket 测试工具推荐',
    description: '推荐的WebSocket测试工具和示例代码'
  })
  @ApiResponse({
    status: 200,
    description: '测试工具和示例代码',
  })
  getTestingTools() {
    return {
      onlineTools: [
        {
          name: 'WebSocket King',
          url: 'https://websocketking.com/',
          description: '在线WebSocket测试工具，支持消息发送和接收'
        },
        {
          name: 'WebSocket Test Client',
          url: 'https://www.websocket.org/echo.html',
          description: '简单的WebSocket回显测试'
        },
        {
          name: '内置测试页面',
          url: '/websocket-test',
          description: '项目内置的WebSocket测试界面，支持完整功能测试'
        }
      ],
      codeExamples: {
        javascript: `
// JavaScript WebSocket 客户端示例
const ws = new WebSocket('wss://whaletownend.xinghangee.icu/game');

ws.onopen = function() {
  console.log('连接成功');
  // 发送登录消息
  ws.send(JSON.stringify({
    type: 'login',
    token: 'your_jwt_token_here'
  }));
};

ws.onmessage = function(event) {
  const data = JSON.parse(event.data);
  console.log('收到消息:', data);
  
  if (data.t === 'login_success') {
    // 登录成功，发送聊天消息
    ws.send(JSON.stringify({
      t: 'chat',
      content: 'Hello from JavaScript!',
      scope: 'local'
    }));
  }
};

ws.onclose = function(event) {
  console.log('连接关闭:', event.code, event.reason);
};

ws.onerror = function(error) {
  console.error('WebSocket错误:', error);
};
        `,
        python: `
# Python WebSocket 客户端示例
import websocket
import json
import threading

def on_message(ws, message):
    data = json.loads(message)
    print(f"收到消息: {data}")
    
    if data.get('t') == 'login_success':
        # 登录成功，发送聊天消息
        ws.send(json.dumps({
            't': 'chat',
            'content': 'Hello from Python!',
            'scope': 'local'
        }))

def on_error(ws, error):
    print(f"WebSocket错误: {error}")

def on_close(ws, close_status_code, close_msg):
    print(f"连接关闭: {close_status_code} - {close_msg}")

def on_open(ws):
    print("连接成功")
    # 发送登录消息
    ws.send(json.dumps({
        'type': 'login',
        'token': 'your_jwt_token_here'
    }))

# 创建WebSocket连接
ws = websocket.WebSocketApp("wss://whaletownend.xinghangee.icu/game",
                          on_message=on_message,
                          on_error=on_error,
                          on_close=on_close,
                          on_open=on_open)

# 启动连接
ws.run_forever()
        `,
        nodejs: `
// Node.js WebSocket 客户端示例
const WebSocket = require('ws');

const ws = new WebSocket('wss://whaletownend.xinghangee.icu/game');

ws.on('open', function() {
    console.log('连接成功');
    
    // 发送登录消息
    ws.send(JSON.stringify({
        type: 'login',
        token: 'your_jwt_token_here'
    }));
});

ws.on('message', function(data) {
    const message = JSON.parse(data.toString());
    console.log('收到消息:', message);
    
    if (message.t === 'login_success') {
        // 登录成功，发送聊天消息
        ws.send(JSON.stringify({
            t: 'chat',
            content: 'Hello from Node.js!',
            scope: 'local'
        }));
    }
});

ws.on('close', function(code, reason) {
    console.log(\`连接关闭: \${code} - \${reason}\`);
});

ws.on('error', function(error) {
    console.error('WebSocket错误:', error);
});
        `
      },
      testingSteps: [
        '1. 访问测试页面: /websocket-test?from=api-docs',
        '2. 点击"🚀 一键测试"按钮自动完成所有步骤',
        '3. 或手动操作: 获取JWT Token → 连接 → 登录',
        '4. 发送chat消息测试聊天功能',
        '5. 发送position消息测试位置更新',
        '6. 观察其他客户端的消息广播'
      ],
      troubleshooting: {
        connectionFailed: [
          '检查网络连接是否正常',
          '验证WebSocket服务器是否启动',
          '确认防火墙设置允许WebSocket连接',
          '检查SSL证书是否有效（WSS连接）'
        ],
        authenticationFailed: [
          '验证JWT Token是否有效且未过期',
          '检查Token格式是否正确',
          '确认Token包含必需的字段（sub, username, email, role）',
          '验证Token的issuer和audience是否匹配'
        ],
        messageFailed: [
          '确认已完成登录认证',
          '检查消息格式是否符合API规范',
          '验证必需字段是否都已提供',
          '检查消息内容是否符合长度限制'
        ]
      }
    };
  }

  @Get('architecture')
  @ApiOperation({
    summary: 'WebSocket 架构信息',
    description: '展示WebSocket服务的技术架构和实现细节'
  })
  @ApiResponse({
    status: 200,
    description: 'WebSocket架构信息',
  })
  getArchitecture() {
    return {
      overview: {
        title: 'WebSocket 架构概览',
        description: '基于原生WebSocket的实时通信架构',
        version: '2.1.0',
        migrationFrom: 'Socket.IO',
        migrationDate: '2026-01-09'
      },
      technicalStack: {
        server: {
          framework: 'NestJS',
          websocketLibrary: 'ws (原生WebSocket)',
          adapter: '@nestjs/platform-ws',
          port: 3001,
          path: '/game'
        },
        proxy: {
          server: 'Nginx',
          sslTermination: true,
          loadBalancing: 'Single Instance',
          pathRouting: '/game -> localhost:3001'
        },
        authentication: {
          method: 'JWT Bearer Token',
          validation: 'Real-time on connection',
          sessionManagement: 'In-memory with Redis backup'
        }
      },
      features: {
        connectionManagement: {
          maxConnections: 1000,
          connectionPooling: true,
          automaticReconnection: 'Client-side',
          heartbeat: '30s interval'
        },
        messaging: {
          messageTypes: ['login', 'chat', 'position'],
          messageRouting: 'Room-based (by map)',
          messageFiltering: 'Content and rate limiting',
          messageHistory: 'Not stored (real-time only)'
        },
        roomManagement: {
          strategy: 'Map-based rooms',
          autoJoin: 'On position update',
          autoLeave: 'On disconnect or map change',
          broadcasting: 'Room-scoped and global'
        }
      },
      performance: {
        latency: '< 50ms (local network)',
        throughput: '1000+ messages/second',
        memoryUsage: '~1MB per 100 connections',
        cpuUsage: 'Low (event-driven)'
      },
      monitoring: {
        metrics: [
          'Active connections count',
          'Messages per second',
          'Authentication success rate',
          'Error rate by type'
        ],
        logging: [
          'Connection events',
          'Authentication attempts',
          'Message routing',
          'Error conditions'
        ],
        healthCheck: '/chat/status endpoint'
      },
      security: {
        authentication: 'JWT Token validation',
        authorization: 'Role-based access control',
        rateLimit: 'Per-user message rate limiting',
        contentFilter: 'Sensitive word filtering',
        inputValidation: 'Message format validation'
      },
      deployment: {
        environment: 'Production ready',
        scaling: 'Horizontal scaling supported',
        backup: 'Session state in Redis',
        monitoring: 'Integrated with application monitoring'
      }
    };
  }
}