/**
 * 位置广播HTTP API控制器
 *
 * 功能描述：
 * - 提供位置广播系统的REST API接口
 * - 处理HTTP请求和响应格式化
 * - 集成JWT认证和权限验证
 * - 提供完整的API文档和错误处理
 *
 * 职责分离：
 * - HTTP处理：专注于HTTP请求和响应的处理
 * - 数据转换：请求参数和响应数据的格式转换
 * - 权限验证：API访问权限的验证和控制
 * - 文档生成：Swagger API文档的自动生成
 *
 * 技术实现：
 * - NestJS控制器：使用装饰器定义API端点
 * - Swagger集成：自动生成API文档
 * - 数据验证：使用DTO进行请求数据验证
 * - 异常处理：统一的HTTP异常处理机制
 *
 * 最近修改：
 * - 2026-01-08: 功能新增 - 创建位置广播HTTP API控制器
 *
 * @author moyin
 * @version 1.0.0
 * @since 2026-01-08
 * @lastModified 2026-01-08
 */

import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  UseGuards,
  HttpStatus,
  HttpException,
  Logger,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiParam,
  ApiQuery,
  ApiBearerAuth,
  ApiBody,
} from '@nestjs/swagger';
import { JwtAuthGuard, AuthenticatedRequest } from '../../gateway/auth/jwt_auth.guard';
import { CurrentUser } from '../../gateway/auth/current_user.decorator';
import { JwtPayload } from '../../core/login_core/login_core.service';

// 导入业务服务
import {
  LocationBroadcastService,
  LocationSessionService,
  LocationPositionService,
} from './services';

// 导入DTO
import {
  CreateSessionDto,
  JoinSessionDto,
  UpdatePositionDto,
  SessionQueryDto,
  PositionQueryDto,
  UpdateSessionConfigDto,
} from './dto/api.dto';

/**
 * 位置广播API控制器
 *
 * 提供以下API端点：
 * - 会话管理：创建、查询、配置会话
 * - 位置管理：查询位置、获取统计信息
 * - 用户管理：获取用户状态、清理数据
 */
@ApiTags('位置广播')
@Controller('location-broadcast')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
export class LocationBroadcastController {
  private readonly logger = new Logger(LocationBroadcastController.name);

  constructor(
    private readonly locationBroadcastService: LocationBroadcastService,
    private readonly locationSessionService: LocationSessionService,
    private readonly locationPositionService: LocationPositionService,
  ) {}

  /**
   * 创建新会话
   */
  @Post('sessions')
  @ApiOperation({
    summary: '创建新会话',
    description: '创建一个新的游戏会话，用于多人位置广播',
  })
  @ApiBody({ type: CreateSessionDto })
  @ApiResponse({
    status: 201,
    description: '会话创建成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        data: {
          type: 'object',
          properties: {
            sessionId: { type: 'string', example: 'session_12345' },
            createdAt: { type: 'number', example: 1641024000000 },
            config: { type: 'object' },
          },
        },
        message: { type: 'string', example: '会话创建成功' },
      },
    },
  })
  @ApiResponse({ status: 400, description: '请求参数错误' })
  @ApiResponse({ status: 409, description: '会话ID已存在' })
  async createSession(
    @Body() createSessionDto: CreateSessionDto,
    @CurrentUser() user: JwtPayload,
  ) {
    try {
      this.logger.log('创建会话API请求', {
        operation: 'createSession',
        sessionId: createSessionDto.sessionId,
        userId: user.sub,
        timestamp: new Date().toISOString(),
      });

      const session = await this.locationSessionService.createSession({
        sessionId: createSessionDto.sessionId,
        creatorId: user.sub,
        name: createSessionDto.name,
        description: createSessionDto.description,
        maxUsers: createSessionDto.maxUsers,
        allowObservers: createSessionDto.allowObservers,
        password: createSessionDto.password,
        allowedMaps: createSessionDto.allowedMaps,
        broadcastRange: createSessionDto.broadcastRange,
        metadata: createSessionDto.metadata,
      });

      return {
        success: true,
        data: {
          sessionId: session.sessionId,
          createdAt: session.createdAt,
          config: session.config,
          metadata: session.metadata,
        },
        message: '会话创建成功',
      };
    } catch (error) {
      this.logger.error('创建会话失败', {
        operation: 'createSession',
        sessionId: createSessionDto.sessionId,
        userId: user.sub,
        error: error instanceof Error ? error.message : String(error),
      });

      if (error instanceof HttpException) {
        throw error;
      }

      throw new HttpException(
        {
          success: false,
          message: '会话创建失败',
          error: error instanceof Error ? error.message : String(error),
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 查询会话列表
   */
  @Get('sessions')
  @ApiOperation({
    summary: '查询会话列表',
    description: '根据条件查询游戏会话列表',
  })
  @ApiQuery({ name: 'status', required: false, description: '会话状态' })
  @ApiQuery({ name: 'minUsers', required: false, description: '最小用户数' })
  @ApiQuery({ name: 'maxUsers', required: false, description: '最大用户数' })
  @ApiQuery({ name: 'publicOnly', required: false, description: '只显示公开会话' })
  @ApiQuery({ name: 'offset', required: false, description: '分页偏移' })
  @ApiQuery({ name: 'limit', required: false, description: '分页大小' })
  @ApiResponse({
    status: 200,
    description: '查询成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        data: {
          type: 'object',
          properties: {
            sessions: { type: 'array', items: { type: 'object' } },
            total: { type: 'number', example: 10 },
            page: { type: 'number', example: 1 },
            pageSize: { type: 'number', example: 10 },
          },
        },
      },
    },
  })
  async querySessions(@Query() query: SessionQueryDto) {
    try {
      const result = await this.locationSessionService.querySessions({
        status: query.status as any, // 类型转换，因为DTO中是string类型
        minUsers: query.minUsers,
        maxUsers: query.maxUsers,
        publicOnly: query.publicOnly,
        offset: query.offset || 0,
        limit: query.limit || 10,
      });

      return {
        success: true,
        data: result,
      };
    } catch (error) {
      this.logger.error('查询会话列表失败', {
        operation: 'querySessions',
        query,
        error: error instanceof Error ? error.message : String(error),
      });

      throw new HttpException(
        {
          success: false,
          message: '查询会话列表失败',
          error: error instanceof Error ? error.message : String(error),
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 获取会话详情
   */
  @Get('sessions/:sessionId')
  @ApiOperation({
    summary: '获取会话详情',
    description: '获取指定会话的详细信息，包括用户列表和位置信息',
  })
  @ApiParam({ name: 'sessionId', description: '会话ID' })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        data: {
          type: 'object',
          properties: {
            session: { type: 'object' },
            users: { type: 'array', items: { type: 'object' } },
            onlineCount: { type: 'number', example: 5 },
            activeMaps: { type: 'array', items: { type: 'string' } },
          },
        },
      },
    },
  })
  @ApiResponse({ status: 404, description: '会话不存在' })
  async getSessionDetail(
    @Param('sessionId') sessionId: string,
    @CurrentUser() user: JwtPayload,
  ) {
    try {
      const result = await this.locationSessionService.getSessionDetail(
        sessionId,
        user.sub,
      );

      return {
        success: true,
        data: result,
      };
    } catch (error) {
      this.logger.error('获取会话详情失败', {
        operation: 'getSessionDetail',
        sessionId,
        userId: user.sub,
        error: error instanceof Error ? error.message : String(error),
      });

      if (error instanceof HttpException) {
        throw error;
      }

      throw new HttpException(
        {
          success: false,
          message: '获取会话详情失败',
          error: error instanceof Error ? error.message : String(error),
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 更新会话配置
   */
  @Put('sessions/:sessionId/config')
  @ApiOperation({
    summary: '更新会话配置',
    description: '更新指定会话的配置参数（需要管理员权限）',
  })
  @ApiParam({ name: 'sessionId', description: '会话ID' })
  @ApiBody({ type: UpdateSessionConfigDto })
  @ApiResponse({
    status: 200,
    description: '更新成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        data: { type: 'object' },
        message: { type: 'string', example: '会话配置更新成功' },
      },
    },
  })
  @ApiResponse({ status: 403, description: '权限不足' })
  @ApiResponse({ status: 404, description: '会话不存在' })
  async updateSessionConfig(
    @Param('sessionId') sessionId: string,
    @Body() updateConfigDto: UpdateSessionConfigDto,
    @CurrentUser() user: JwtPayload,
  ) {
    try {
      const session = await this.locationSessionService.updateSessionConfig(
        sessionId,
        updateConfigDto,
        user.sub,
      );

      return {
        success: true,
        data: session,
        message: '会话配置更新成功',
      };
    } catch (error) {
      this.logger.error('更新会话配置失败', {
        operation: 'updateSessionConfig',
        sessionId,
        userId: user.sub,
        error: error instanceof Error ? error.message : String(error),
      });

      if (error instanceof HttpException) {
        throw error;
      }

      throw new HttpException(
        {
          success: false,
          message: '更新会话配置失败',
          error: error instanceof Error ? error.message : String(error),
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 结束会话
   */
  @Delete('sessions/:sessionId')
  @ApiOperation({
    summary: '结束会话',
    description: '结束指定的游戏会话（需要管理员权限）',
  })
  @ApiParam({ name: 'sessionId', description: '会话ID' })
  @ApiResponse({
    status: 200,
    description: '会话结束成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '会话结束成功' },
      },
    },
  })
  @ApiResponse({ status: 403, description: '权限不足' })
  @ApiResponse({ status: 404, description: '会话不存在' })
  async endSession(
    @Param('sessionId') sessionId: string,
    @CurrentUser() user: JwtPayload,
  ) {
    try {
      await this.locationSessionService.endSession(sessionId, user.sub);

      return {
        success: true,
        message: '会话结束成功',
      };
    } catch (error) {
      this.logger.error('结束会话失败', {
        operation: 'endSession',
        sessionId,
        userId: user.sub,
        error: error instanceof Error ? error.message : String(error),
      });

      if (error instanceof HttpException) {
        throw error;
      }

      throw new HttpException(
        {
          success: false,
          message: '结束会话失败',
          error: error instanceof Error ? error.message : String(error),
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 查询位置信息
   */
  @Get('positions')
  @ApiOperation({
    summary: '查询位置信息',
    description: '根据条件查询用户位置信息',
  })
  @ApiQuery({ name: 'userIds', required: false, description: '用户ID列表（逗号分隔）' })
  @ApiQuery({ name: 'mapId', required: false, description: '地图ID' })
  @ApiQuery({ name: 'sessionId', required: false, description: '会话ID' })
  @ApiQuery({ name: 'centerX', required: false, description: '范围查询中心X坐标' })
  @ApiQuery({ name: 'centerY', required: false, description: '范围查询中心Y坐标' })
  @ApiQuery({ name: 'radius', required: false, description: '范围查询半径' })
  @ApiQuery({ name: 'offset', required: false, description: '分页偏移' })
  @ApiQuery({ name: 'limit', required: false, description: '分页大小' })
  @ApiResponse({
    status: 200,
    description: '查询成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        data: {
          type: 'object',
          properties: {
            positions: { type: 'array', items: { type: 'object' } },
            total: { type: 'number', example: 20 },
            timestamp: { type: 'number', example: 1641024000000 },
          },
        },
      },
    },
  })
  async queryPositions(@Query() query: PositionQueryDto) {
    try {
      const userIds = query.userIds ? query.userIds.split(',') : undefined;
      const range = (query.centerX !== undefined && query.centerY !== undefined && query.radius !== undefined) ? {
        centerX: query.centerX,
        centerY: query.centerY,
        radius: query.radius,
      } : undefined;

      const result = await this.locationPositionService.queryPositions({
        userIds,
        mapId: query.mapId,
        sessionId: query.sessionId,
        range,
        pagination: {
          offset: query.offset || 0,
          limit: query.limit || 50,
        },
      });

      return {
        success: true,
        data: result,
      };
    } catch (error) {
      this.logger.error('查询位置信息失败', {
        operation: 'queryPositions',
        query,
        error: error instanceof Error ? error.message : String(error),
      });

      throw new HttpException(
        {
          success: false,
          message: '查询位置信息失败',
          error: error instanceof Error ? error.message : String(error),
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 获取位置统计信息
   */
  @Get('positions/stats')
  @ApiOperation({
    summary: '获取位置统计信息',
    description: '获取位置数据的统计信息，包括用户分布、活跃地图等',
  })
  @ApiQuery({ name: 'mapId', required: false, description: '地图ID' })
  @ApiQuery({ name: 'sessionId', required: false, description: '会话ID' })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        data: {
          type: 'object',
          properties: {
            totalUsers: { type: 'number', example: 100 },
            onlineUsers: { type: 'number', example: 85 },
            activeMaps: { type: 'number', example: 5 },
            mapDistribution: { type: 'object' },
            updateFrequency: { type: 'number', example: 2.5 },
            timestamp: { type: 'number', example: 1641024000000 },
          },
        },
      },
    },
  })
  async getPositionStats(
    @Query('mapId') mapId?: string,
    @Query('sessionId') sessionId?: string,
  ) {
    try {
      const result = await this.locationPositionService.getPositionStats({
        mapId,
        sessionId,
      });

      return {
        success: true,
        data: result,
      };
    } catch (error) {
      this.logger.error('获取位置统计失败', {
        operation: 'getPositionStats',
        mapId,
        sessionId,
        error: error instanceof Error ? error.message : String(error),
      });

      throw new HttpException(
        {
          success: false,
          message: '获取位置统计失败',
          error: error instanceof Error ? error.message : String(error),
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 获取用户位置历史
   */
  @Get('users/:userId/position-history')
  @ApiOperation({
    summary: '获取用户位置历史',
    description: '获取指定用户的位置历史记录',
  })
  @ApiParam({ name: 'userId', description: '用户ID' })
  @ApiQuery({ name: 'mapId', required: false, description: '地图ID过滤' })
  @ApiQuery({ name: 'limit', required: false, description: '最大记录数' })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        data: {
          type: 'array',
          items: { type: 'object' },
        },
      },
    },
  })
  async getUserPositionHistory(
    @Param('userId') userId: string,
    @CurrentUser() user: JwtPayload,
    @Query('mapId') mapId?: string,
    @Query('limit') limit?: number,
  ) {
    try {
      // 权限检查：只能查看自己的历史记录，或者管理员可以查看所有
      if (userId !== user.sub && user.role < 2) {
        throw new HttpException(
          {
            success: false,
            message: '权限不足，只能查看自己的位置历史',
          },
          HttpStatus.FORBIDDEN,
        );
      }

      const result = await this.locationPositionService.getPositionHistory({
        userId,
        mapId,
        limit: limit || 100,
      });

      return {
        success: true,
        data: result,
      };
    } catch (error) {
      this.logger.error('获取用户位置历史失败', {
        operation: 'getUserPositionHistory',
        userId,
        requestUserId: user.sub,
        error: error instanceof Error ? error.message : String(error),
      });

      if (error instanceof HttpException) {
        throw error;
      }

      throw new HttpException(
        {
          success: false,
          message: '获取用户位置历史失败',
          error: error instanceof Error ? error.message : String(error),
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 清理用户数据
   */
  @Delete('users/:userId/data')
  @ApiOperation({
    summary: '清理用户数据',
    description: '清理指定用户的位置广播相关数据（需要管理员权限）',
  })
  @ApiParam({ name: 'userId', description: '用户ID' })
  @ApiResponse({
    status: 200,
    description: '清理成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '用户数据清理成功' },
      },
    },
  })
  @ApiResponse({ status: 403, description: '权限不足' })
  async cleanupUserData(
    @Param('userId') userId: string,
    @CurrentUser() user: JwtPayload,
  ) {
    try {
      // 权限检查：只有管理员或用户本人可以清理数据
      if (userId !== user.sub && user.role < 2) {
        throw new HttpException(
          {
            success: false,
            message: '权限不足，只能清理自己的数据',
          },
          HttpStatus.FORBIDDEN,
        );
      }

      const success = await this.locationBroadcastService.cleanupUserData(userId);

      if (!success) {
        throw new HttpException(
          {
            success: false,
            message: '用户数据清理失败',
          },
          HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }

      return {
        success: true,
        message: '用户数据清理成功',
      };
    } catch (error) {
      this.logger.error('清理用户数据失败', {
        operation: 'cleanupUserData',
        userId,
        operatorId: user.sub,
        error: error instanceof Error ? error.message : String(error),
      });

      if (error instanceof HttpException) {
        throw error;
      }

      throw new HttpException(
        {
          success: false,
          message: '清理用户数据失败',
          error: error instanceof Error ? error.message : String(error),
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}