/**
 * Zulip账号关联管理控制器
 *
 * 功能描述：
 * - 提供Zulip账号关联管理的REST API接口
 * - 支持CRUD操作和批量管理
 * - 提供账号验证和统计功能
 * - 集成性能监控和结构化日志记录
 * - 实现统一的错误处理和响应格式
 *
 * 架构定位：
 * - 层级：Gateway层（网关层）
 * - 职责：HTTP协议处理、API接口暴露
 * - 依赖：调用Business层的ZulipAccountsBusinessService
 *
 * 职责分离：
 * - API接口：提供RESTful风格的HTTP接口
 * - 参数验证：使用DTO进行请求参数验证
 * - 业务调用：调用Service层处理业务逻辑
 * - 响应格式：统一API响应格式和错误处理
 * - 性能监控：记录接口调用耗时和性能指标
 * - 日志记录：使用AppLoggerService记录结构化日志
 *
 * 最近修改：
 * - 2026-01-14: 架构优化 - 从Business层迁移到Gateway层，符合四层架构规范 (修改者: moyin)
 * - 2026-01-14: 代码质量优化 - 移除未使用的requestLogger属性 (修改者: moyin)
 * - 2026-01-14: 代码质量优化 - 移除未使用的导入 (修改者: moyin)
 * - 2026-01-12: 性能优化 - 集成AppLoggerService和性能监控，优化错误处理
 * - 2025-01-07: 初始创建 - 实现基础的CRUD和管理接口
 *
 * @author angjustinl
 * @version 2.0.0
 * @since 2025-01-07
 * @lastModified 2026-01-14
 */

import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  UseGuards,
  HttpStatus,
  HttpCode,
  Inject,
  Req,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiParam,
  ApiQuery,
} from '@nestjs/swagger';
import { Request } from 'express';
import { JwtAuthGuard } from '../auth/jwt_auth.guard';
import { AppLoggerService } from '../../core/utils/logger/logger.service';
import {
  CreateZulipAccountDto,
  UpdateZulipAccountDto,
  QueryZulipAccountDto,
  ZulipAccountResponseDto,
  ZulipAccountListResponseDto,
  ZulipAccountStatsResponseDto,
  BatchUpdateStatusDto,
  BatchUpdateResponseDto,
  VerifyAccountDto,
  VerifyAccountResponseDto,
} from '../../core/db/zulip_accounts/zulip_accounts.dto';

@ApiTags('zulip-accounts')
@Controller('zulip-accounts')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth('JWT-auth')
export class ZulipAccountsController {
  constructor(
    @Inject('ZulipAccountsService') private readonly zulipAccountsService: any,
    @Inject(AppLoggerService) private readonly logger: AppLoggerService,
  ) {
    this.logger.info('ZulipAccountsController初始化完成', {
      module: 'ZulipAccountsController',
      operation: 'constructor'
    });
  }

  /**
   * 创建性能监控器
   *
   * @param req HTTP请求对象
   * @param operation 操作名称
   * @param context 上下文信息
   * @returns 性能监控器
   * @private
   */
  private createPerformanceMonitor(req: Request, operation: string, context?: Record<string, any>) {
    const startTime = Date.now();
    const requestLogger = this.logger.bindRequest(req, 'ZulipAccountsController');

    requestLogger.info(`开始${operation}`, context);

    return {
      success: (additionalContext?: Record<string, any>) => {
        const duration = Date.now() - startTime;
        requestLogger.info(`${operation}成功`, {
          ...context,
          ...additionalContext,
          duration
        });
      },
      error: (error: unknown, additionalContext?: Record<string, any>) => {
        const duration = Date.now() - startTime;
        const errorMessage = error instanceof Error ? error.message : String(error);
        requestLogger.error(
          `${operation}失败`,
          error instanceof Error ? error.stack : undefined,
          {
            ...context,
            ...additionalContext,
            error: errorMessage,
            duration
          }
        );
      }
    };
  }

  /**
   * 创建Zulip账号关联
   */
  @Post()
  @ApiOperation({
    summary: '创建Zulip账号关联',
    description: '为游戏用户创建与Zulip账号的关联关系'
  })
  @ApiResponse({
    status: 201,
    description: '创建成功',
    type: ZulipAccountResponseDto,
  })
  @ApiResponse({
    status: 400,
    description: '请求参数错误',
  })
  @ApiResponse({
    status: 409,
    description: '关联已存在',
  })
  @HttpCode(HttpStatus.CREATED)
  async create(
    @Req() req: Request,
    @Body() createDto: CreateZulipAccountDto
  ): Promise<ZulipAccountResponseDto> {
    const monitor = this.createPerformanceMonitor(req, '创建Zulip账号关联', {
      gameUserId: createDto.gameUserId,
      zulipUserId: createDto.zulipUserId,
      zulipEmail: createDto.zulipEmail
    });

    try {
      const result = await this.zulipAccountsService.create(createDto);
      monitor.success({
        accountId: result.id,
        status: result.status
      });
      return result;
    } catch (error) {
      monitor.error(error);
      throw error;
    }
  }

  /**
   * 获取所有Zulip账号关联
   */
  @Get()
  @ApiOperation({
    summary: '查询Zulip账号关联列表',
    description: '根据条件查询Zulip账号关联列表'
  })
  @ApiQuery({
    name: 'gameUserId',
    required: false,
    description: '游戏用户ID',
    example: '12345'
  })
  @ApiQuery({
    name: 'zulipUserId',
    required: false,
    description: 'Zulip用户ID',
    example: 67890
  })
  @ApiQuery({
    name: 'zulipEmail',
    required: false,
    description: 'Zulip邮箱地址',
    example: 'user@example.com'
  })
  @ApiQuery({
    name: 'status',
    required: false,
    description: '账号状态',
    enum: ['active', 'inactive', 'suspended', 'error']
  })
  @ApiQuery({
    name: 'includeGameUser',
    required: false,
    description: '是否包含游戏用户信息',
    type: Boolean,
    example: false
  })
  @ApiResponse({
    status: 200,
    description: '查询成功',
    type: ZulipAccountListResponseDto,
  })
  async findMany(@Query() queryDto: QueryZulipAccountDto): Promise<ZulipAccountListResponseDto> {
    return this.zulipAccountsService.findMany(queryDto);
  }

  /**
   * 根据ID获取Zulip账号关联
   */
  @Get(':id')
  @ApiOperation({
    summary: '根据ID获取Zulip账号关联',
    description: '根据关联记录ID获取详细信息'
  })
  @ApiParam({
    name: 'id',
    description: '关联记录ID',
    example: '1'
  })
  @ApiQuery({
    name: 'includeGameUser',
    required: false,
    description: '是否包含游戏用户信息',
    type: Boolean,
    example: false
  })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    type: ZulipAccountResponseDto,
  })
  @ApiResponse({
    status: 404,
    description: '记录不存在',
  })
  async findById(
    @Param('id') id: string,
    @Query('includeGameUser') includeGameUser?: boolean,
  ): Promise<ZulipAccountResponseDto> {
    return this.zulipAccountsService.findById(id, includeGameUser);
  }

  /**
   * 根据游戏用户ID获取Zulip账号关联
   */
  @Get('game-user/:gameUserId')
  @ApiOperation({
    summary: '根据游戏用户ID获取Zulip账号关联',
    description: '根据游戏用户ID获取关联的Zulip账号信息'
  })
  @ApiParam({
    name: 'gameUserId',
    description: '游戏用户ID',
    example: '12345'
  })
  @ApiQuery({
    name: 'includeGameUser',
    required: false,
    description: '是否包含游戏用户信息',
    type: Boolean,
    example: false
  })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    type: ZulipAccountResponseDto,
  })
  @ApiResponse({
    status: 404,
    description: '关联不存在',
  })
  async findByGameUserId(
    @Param('gameUserId') gameUserId: string,
    @Query('includeGameUser') includeGameUser?: boolean,
  ): Promise<ZulipAccountResponseDto | null> {
    return this.zulipAccountsService.findByGameUserId(gameUserId, includeGameUser);
  }

  /**
   * 根据Zulip用户ID获取账号关联
   */
  @Get('zulip-user/:zulipUserId')
  @ApiOperation({
    summary: '根据Zulip用户ID获取账号关联',
    description: '根据Zulip用户ID获取关联的游戏账号信息'
  })
  @ApiParam({
    name: 'zulipUserId',
    description: 'Zulip用户ID',
    example: '67890'
  })
  @ApiQuery({
    name: 'includeGameUser',
    required: false,
    description: '是否包含游戏用户信息',
    type: Boolean,
    example: false
  })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    type: ZulipAccountResponseDto,
  })
  @ApiResponse({
    status: 404,
    description: '关联不存在',
  })
  async findByZulipUserId(
    @Param('zulipUserId') zulipUserId: string,
    @Query('includeGameUser') includeGameUser?: boolean,
  ): Promise<ZulipAccountResponseDto | null> {
    return this.zulipAccountsService.findByZulipUserId(parseInt(zulipUserId), includeGameUser);
  }

  /**
   * 根据Zulip邮箱获取账号关联
   */
  @Get('zulip-email/:zulipEmail')
  @ApiOperation({
    summary: '根据Zulip邮箱获取账号关联',
    description: '根据Zulip邮箱地址获取关联的游戏账号信息'
  })
  @ApiParam({
    name: 'zulipEmail',
    description: 'Zulip邮箱地址',
    example: 'user@example.com'
  })
  @ApiQuery({
    name: 'includeGameUser',
    required: false,
    description: '是否包含游戏用户信息',
    type: Boolean,
    example: false
  })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    type: ZulipAccountResponseDto,
  })
  @ApiResponse({
    status: 404,
    description: '关联不存在',
  })
  async findByZulipEmail(
    @Param('zulipEmail') zulipEmail: string,
    @Query('includeGameUser') includeGameUser?: boolean,
  ): Promise<ZulipAccountResponseDto | null> {
    return this.zulipAccountsService.findByZulipEmail(zulipEmail, includeGameUser);
  }

  /**
   * 更新Zulip账号关联
   */
  @Put(':id')
  @ApiOperation({
    summary: '更新Zulip账号关联',
    description: '根据ID更新Zulip账号关联信息'
  })
  @ApiParam({
    name: 'id',
    description: '关联记录ID',
    example: '1'
  })
  @ApiResponse({
    status: 200,
    description: '更新成功',
    type: ZulipAccountResponseDto,
  })
  @ApiResponse({
    status: 404,
    description: '记录不存在',
  })
  async update(
    @Param('id') id: string,
    @Body() updateDto: UpdateZulipAccountDto,
  ): Promise<ZulipAccountResponseDto> {
    return this.zulipAccountsService.update(id, updateDto);
  }

  /**
   * 根据游戏用户ID更新关联
   */
  @Put('game-user/:gameUserId')
  @ApiOperation({
    summary: '根据游戏用户ID更新关联',
    description: '根据游戏用户ID更新Zulip账号关联信息'
  })
  @ApiParam({
    name: 'gameUserId',
    description: '游戏用户ID',
    example: '12345'
  })
  @ApiResponse({
    status: 200,
    description: '更新成功',
    type: ZulipAccountResponseDto,
  })
  @ApiResponse({
    status: 404,
    description: '关联不存在',
  })
  async updateByGameUserId(
    @Param('gameUserId') gameUserId: string,
    @Body() updateDto: UpdateZulipAccountDto,
  ): Promise<ZulipAccountResponseDto> {
    return this.zulipAccountsService.updateByGameUserId(gameUserId, updateDto);
  }

  /**
   * 删除Zulip账号关联
   */
  @Delete(':id')
  @ApiOperation({
    summary: '删除Zulip账号关联',
    description: '根据ID删除Zulip账号关联记录'
  })
  @ApiParam({
    name: 'id',
    description: '关联记录ID',
    example: '1'
  })
  @ApiResponse({
    status: 200,
    description: '删除成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '删除成功' }
      }
    }
  })
  @ApiResponse({
    status: 404,
    description: '记录不存在',
  })
  async delete(@Param('id') id: string): Promise<{ success: boolean; message: string }> {
    await this.zulipAccountsService.delete(id);
    return { success: true, message: '删除成功' };
  }

  /**
   * 根据游戏用户ID删除关联
   */
  @Delete('game-user/:gameUserId')
  @ApiOperation({
    summary: '根据游戏用户ID删除关联',
    description: '根据游戏用户ID删除Zulip账号关联记录'
  })
  @ApiParam({
    name: 'gameUserId',
    description: '游戏用户ID',
    example: '12345'
  })
  @ApiResponse({
    status: 200,
    description: '删除成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '删除成功' }
      }
    }
  })
  @ApiResponse({
    status: 404,
    description: '关联不存在',
  })
  async deleteByGameUserId(@Param('gameUserId') gameUserId: string): Promise<{ success: boolean; message: string }> {
    await this.zulipAccountsService.deleteByGameUserId(gameUserId);
    return { success: true, message: '删除成功' };
  }

  /**
   * 获取需要验证的账号列表
   */
  @Get('management/verification-needed')
  @ApiOperation({
    summary: '获取需要验证的账号列表',
    description: '获取超过指定时间未验证的账号列表'
  })
  @ApiQuery({
    name: 'maxAge',
    required: false,
    description: '最大验证间隔（毫秒），默认24小时',
    example: 86400000
  })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    type: ZulipAccountListResponseDto,
  })
  async findAccountsNeedingVerification(
    @Query('maxAge') maxAge?: number,
  ): Promise<ZulipAccountListResponseDto> {
    return this.zulipAccountsService.findAccountsNeedingVerification(maxAge);
  }

  /**
   * 获取错误状态的账号列表
   */
  @Get('management/error-accounts')
  @ApiOperation({
    summary: '获取错误状态的账号列表',
    description: '获取处于错误状态的账号列表'
  })
  @ApiQuery({
    name: 'maxRetryCount',
    required: false,
    description: '最大重试次数，默认3次',
    example: 3
  })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    type: ZulipAccountListResponseDto,
  })
  async findErrorAccounts(
    @Query('maxRetryCount') maxRetryCount?: number,
  ): Promise<ZulipAccountListResponseDto> {
    return this.zulipAccountsService.findErrorAccounts(maxRetryCount);
  }

  /**
   * 批量更新账号状态
   */
  @Put('management/batch-status')
  @ApiOperation({
    summary: '批量更新账号状态',
    description: '批量更新多个账号的状态'
  })
  @ApiResponse({
    status: 200,
    description: '更新成功',
    type: BatchUpdateResponseDto,
  })
  async batchUpdateStatus(@Body() batchDto: BatchUpdateStatusDto): Promise<BatchUpdateResponseDto> {
    return this.zulipAccountsService.batchUpdateStatus(batchDto.ids, batchDto.status);
  }

  /**
   * 获取账号状态统计
   */
  @Get('management/statistics')
  @ApiOperation({
    summary: '获取账号状态统计',
    description: '获取各种状态的账号数量统计'
  })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    type: ZulipAccountStatsResponseDto,
  })
  async getStatusStatistics(@Req() req: Request): Promise<ZulipAccountStatsResponseDto> {
    const monitor = this.createPerformanceMonitor(req, '获取账号状态统计');

    try {
      const result = await this.zulipAccountsService.getStatusStatistics();
      monitor.success({
        total: result.total,
        active: result.active,
        error: result.error
      });
      return result;
    } catch (error) {
      monitor.error(error);
      throw error;
    }
  }

  /**
   * 验证账号有效性
   */
  @Post('management/verify')
  @ApiOperation({
    summary: '验证账号有效性',
    description: '验证指定游戏用户的Zulip账号关联是否有效'
  })
  @ApiResponse({
    status: 200,
    description: '验证完成',
    type: VerifyAccountResponseDto,
  })
  async verifyAccount(@Body() verifyDto: VerifyAccountDto): Promise<VerifyAccountResponseDto> {
    return this.zulipAccountsService.verifyAccount(verifyDto.gameUserId);
  }

  /**
   * 检查邮箱是否已存在
   */
  @Get('validation/email-exists/:email')
  @ApiOperation({
    summary: '检查邮箱是否已存在',
    description: '检查指定的Zulip邮箱是否已被其他账号使用'
  })
  @ApiParam({
    name: 'email',
    description: 'Zulip邮箱地址',
    example: 'user@example.com'
  })
  @ApiQuery({
    name: 'excludeId',
    required: false,
    description: '排除的记录ID（用于更新时检查）',
    example: '1'
  })
  @ApiResponse({
    status: 200,
    description: '检查完成',
    schema: {
      type: 'object',
      properties: {
        exists: { type: 'boolean', example: false },
        email: { type: 'string', example: 'user@example.com' }
      }
    }
  })
  async checkEmailExists(
    @Param('email') email: string,
    @Query('excludeId') excludeId?: string,
  ): Promise<{ exists: boolean; email: string }> {
    const exists = await this.zulipAccountsService.existsByEmail(email, excludeId);
    return { exists, email };
  }

  /**
   * 检查Zulip用户ID是否已存在
   */
  @Get('validation/zulip-user-exists/:zulipUserId')
  @ApiOperation({
    summary: '检查Zulip用户ID是否已存在',
    description: '检查指定的Zulip用户ID是否已被其他账号使用'
  })
  @ApiParam({
    name: 'zulipUserId',
    description: 'Zulip用户ID',
    example: '67890'
  })
  @ApiQuery({
    name: 'excludeId',
    required: false,
    description: '排除的记录ID（用于更新时检查）',
    example: '1'
  })
  @ApiResponse({
    status: 200,
    description: '检查完成',
    schema: {
      type: 'object',
      properties: {
        exists: { type: 'boolean', example: false },
        zulipUserId: { type: 'number', example: 67890 }
      }
    }
  })
  async checkZulipUserIdExists(
    @Param('zulipUserId') zulipUserId: string,
    @Query('excludeId') excludeId?: string,
  ): Promise<{ exists: boolean; zulipUserId: number }> {
    const zulipUserIdNum = parseInt(zulipUserId);
    const exists = await this.zulipAccountsService.existsByZulipUserId(zulipUserIdNum, excludeId);
    return { exists, zulipUserId: zulipUserIdNum };
  }
}