import {
  Body,
  Controller,
  Get,
  Param,
  ParseIntPipe,
  Post,
  Put,
  Query,
  Request,
  UseGuards,
  UsePipes,
  ValidationPipe,
} from '@nestjs/common';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RequirePermission } from '../auth/decorators/permission.decorator';
import { extractRequestInfo } from '../common/request-utils';
import { OperationLogsService } from '../operation-logs/operation-logs.service';
import type { AuthenticatedUser } from '../authorization';
import { CreateExamDto, QueryExamDto, UpdateExamScoreValueDto } from './dto/exam.dto';
import { ExamsService } from './exams.service';

interface AuthenticatedRequest {
  user: AuthenticatedUser;
  ip?: string;
  headers?: Record<string, string | string[] | undefined>;
}

@UseGuards(JwtAuthGuard)
@UsePipes(new ValidationPipe({ transform: true, whitelist: true, forbidNonWhitelisted: true }))
@Controller('exams')
export class ExamsController {
  constructor(
    private readonly service: ExamsService,
    private readonly logService: OperationLogsService,
  ) {}

  private canManageAll(req: AuthenticatedRequest) {
    return req.user.isSuperAdmin || req.user.permissions.includes('exam:edit');
  }

  @Get()
  @RequirePermission('exam:view')
  async findAll(@Query() query: QueryExamDto, @Request() req: AuthenticatedRequest) {
    const classIds = await this.service.getAccessibleClassIds(req.user.id, this.canManageAll(req));
    return this.service.findAll(query, classIds);
  }

  @Get(':id')
  @RequirePermission('exam:view')
  findOne(@Param('id', ParseIntPipe) id: number, @Request() req: AuthenticatedRequest) {
    return this.service.findOne(id, req.user.id, this.canManageAll(req));
  }

  @Post()
  @RequirePermission('exam:view')
  async create(@Body() dto: CreateExamDto, @Request() req: AuthenticatedRequest) {
    const result = await this.service.create(dto, req.user.id, this.canManageAll(req));
    const { ipAddress, userAgent } = extractRequestInfo(req);
    await this.logService.log({
      userId: req.user.id,
      username: req.user.username,
      module: '考试管理',
      action: '创建考试',
      targetId: result.id,
      targetType: 'exam',
      detail: `${dto.examName} - ${dto.subject}`,
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Put(':examId/scores/:scoreId')
  @RequirePermission('exam:view')
  async updateScore(
    @Param('examId', ParseIntPipe) examId: number,
    @Param('scoreId', ParseIntPipe) scoreId: number,
    @Body() dto: UpdateExamScoreValueDto,
    @Request() req: AuthenticatedRequest,
  ) {
    const result = await this.service.updateScore(
      examId,
      scoreId,
      dto.score,
      req.user.id,
      this.canManageAll(req),
    );
    const { ipAddress, userAgent } = extractRequestInfo(req);
    await this.logService.log({
      userId: req.user.id,
      username: req.user.username,
      module: '考试管理',
      action: dto.score === null || dto.score === undefined ? '清空成绩' : '录入成绩',
      targetId: scoreId,
      targetType: 'exam_score',
      detail: dto.score === null || dto.score === undefined ? '成绩已清空' : `成绩：${dto.score}`,
      ipAddress,
      userAgent,
    });
    return result;
  }

}
