import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from '@nestjs/swagger';
import { CoManagedWalletService } from '../../application/services/co-managed-wallet.service';
import {
  CreateCoManagedWalletSessionDto,
  JoinSessionDto,
  ValidateInviteCodeDto,
  ListSessionsDto,
  ListWalletsDto,
  UpdateSessionStatusDto,
} from '../dto/request/co-managed-wallet.dto';
import {
  CoManagedWalletSessionDto,
  CreateSessionResponseDto,
  ValidateInviteCodeResponseDto,
  SessionListResponseDto,
  CoManagedWalletDto,
  WalletListResponseDto,
  ThresholdDto,
} from '../dto/response/co-managed-wallet.dto';
import { WalletSessionStatus } from '../../domain/enums/wallet-session-status.enum';

@ApiTags('共管钱包')
@Controller('admin/co-managed-wallets')
export class CoManagedWalletController {
  constructor(private readonly walletService: CoManagedWalletService) {}

  /**
   * 创建共管钱包会话
   */
  @Post('sessions')
  @ApiOperation({ summary: '创建共管钱包会话' })
  @ApiResponse({ status: 201, type: CreateSessionResponseDto })
  async createSession(
    @Body() dto: CreateCoManagedWalletSessionDto,
  ): Promise<CreateSessionResponseDto> {
    // TODO: 从认证上下文获取用户 ID
    const createdBy = 'admin-user';

    const session = await this.walletService.createSession({
      walletName: dto.walletName,
      thresholdT: dto.thresholdT,
      thresholdN: dto.thresholdN,
      initiatorName: dto.initiatorName,
      createdBy,
    });

    return {
      success: true,
      session: CoManagedWalletSessionDto.fromEntity(session),
    };
  }

  /**
   * 验证邀请码
   */
  @Post('sessions/validate-invite')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '验证邀请码' })
  @ApiResponse({ status: 200, type: ValidateInviteCodeResponseDto })
  async validateInviteCode(
    @Body() dto: ValidateInviteCodeDto,
  ): Promise<ValidateInviteCodeResponseDto> {
    const result = await this.walletService.validateInviteCode(dto.inviteCode);

    if (!result.valid || !result.session) {
      return {
        valid: false,
        error: result.error,
      };
    }

    const session = result.session;
    return {
      valid: true,
      session: {
        sessionId: session.id,
        walletName: session.walletName,
        threshold: ThresholdDto.fromThreshold(session.threshold),
        initiator: session.participants[0]?.name || 'Unknown',
        createdAt: session.createdAt.toISOString(),
        currentParticipants: session.participants.length,
      },
    };
  }

  /**
   * 加入会话
   */
  @Post('sessions/:sessionId/join')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '加入会话' })
  @ApiParam({ name: 'sessionId', description: '会话 ID' })
  @ApiResponse({ status: 200, type: CoManagedWalletSessionDto })
  async joinSession(
    @Param('sessionId') sessionId: string,
    @Body() dto: JoinSessionDto,
  ): Promise<CoManagedWalletSessionDto> {
    const session = await this.walletService.getSession(sessionId);
    const updatedSession = await this.walletService.joinSession(
      session.inviteCode,
      dto.participantName,
      dto.partyId,
    );
    return CoManagedWalletSessionDto.fromEntity(updatedSession);
  }

  /**
   * 获取会话详情
   */
  @Get('sessions/:sessionId')
  @ApiOperation({ summary: '获取会话详情' })
  @ApiParam({ name: 'sessionId', description: '会话 ID' })
  @ApiResponse({ status: 200, type: CoManagedWalletSessionDto })
  async getSession(
    @Param('sessionId') sessionId: string,
  ): Promise<CoManagedWalletSessionDto> {
    const session = await this.walletService.getSession(sessionId);
    return CoManagedWalletSessionDto.fromEntity(session);
  }

  /**
   * 获取会话列表
   */
  @Get('sessions')
  @ApiOperation({ summary: '获取会话列表' })
  @ApiResponse({ status: 200, type: SessionListResponseDto })
  async listSessions(@Query() dto: ListSessionsDto): Promise<SessionListResponseDto> {
    const result = await this.walletService.listSessions({
      page: dto.page ?? 1,
      pageSize: dto.pageSize ?? 10,
      status: dto.status,
    });

    return {
      items: result.items.map((s) => CoManagedWalletSessionDto.fromEntity(s)),
      total: result.total,
      page: result.page,
      pageSize: result.pageSize,
      totalPages: result.totalPages,
    };
  }

  /**
   * 开始密钥生成
   */
  @Post('sessions/:sessionId/start-keygen')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '开始密钥生成' })
  @ApiParam({ name: 'sessionId', description: '会话 ID' })
  @ApiResponse({ status: 200, type: CoManagedWalletSessionDto })
  async startKeygen(
    @Param('sessionId') sessionId: string,
  ): Promise<CoManagedWalletSessionDto> {
    const session = await this.walletService.startKeygen(sessionId);
    return CoManagedWalletSessionDto.fromEntity(session);
  }

  /**
   * 更新会话状态 (内部回调使用)
   */
  @Put('sessions/:sessionId/status')
  @ApiOperation({ summary: '更新会话状态' })
  @ApiParam({ name: 'sessionId', description: '会话 ID' })
  @ApiResponse({ status: 200, type: CoManagedWalletSessionDto })
  async updateSessionStatus(
    @Param('sessionId') sessionId: string,
    @Body() dto: UpdateSessionStatusDto,
  ): Promise<CoManagedWalletSessionDto> {
    let session;

    switch (dto.status) {
      case WalletSessionStatus.PROCESSING:
        if (dto.currentRound !== undefined) {
          session = await this.walletService.updateSessionRound(sessionId, dto.currentRound);
        } else {
          session = await this.walletService.startKeygen(sessionId);
        }
        break;

      case WalletSessionStatus.COMPLETED:
        if (!dto.publicKey) {
          throw new Error('完成状态需要提供公钥');
        }
        const result = await this.walletService.completeSession(sessionId, dto.publicKey);
        session = result.session;
        break;

      case WalletSessionStatus.FAILED:
        session = await this.walletService.failSession(sessionId, dto.error || '未知错误');
        break;

      case WalletSessionStatus.CANCELLED:
        await this.walletService.cancelSession(sessionId);
        session = await this.walletService.getSession(sessionId);
        break;

      default:
        throw new Error('不支持的状态更新');
    }

    return CoManagedWalletSessionDto.fromEntity(session);
  }

  /**
   * 取消会话
   */
  @Delete('sessions/:sessionId')
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiOperation({ summary: '取消会话' })
  @ApiParam({ name: 'sessionId', description: '会话 ID' })
  @ApiResponse({ status: 204 })
  async cancelSession(@Param('sessionId') sessionId: string): Promise<void> {
    await this.walletService.cancelSession(sessionId);
  }

  /**
   * 获取钱包列表
   */
  @Get()
  @ApiOperation({ summary: '获取共管钱包列表' })
  @ApiResponse({ status: 200, type: WalletListResponseDto })
  async listWallets(@Query() dto: ListWalletsDto): Promise<WalletListResponseDto> {
    const result = await this.walletService.listWallets({
      page: dto.page ?? 1,
      pageSize: dto.pageSize ?? 10,
    });

    return {
      items: result.items.map((w) => CoManagedWalletDto.fromEntity(w)),
      total: result.total,
      page: result.page,
      pageSize: result.pageSize,
      totalPages: result.totalPages,
    };
  }

  /**
   * 获取钱包详情
   */
  @Get(':walletId')
  @ApiOperation({ summary: '获取钱包详情' })
  @ApiParam({ name: 'walletId', description: '钱包 ID' })
  @ApiResponse({ status: 200, type: CoManagedWalletDto })
  async getWallet(@Param('walletId') walletId: string): Promise<CoManagedWalletDto> {
    const wallet = await this.walletService.getWallet(walletId);
    return CoManagedWalletDto.fromEntity(wallet);
  }
}
