import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  UseGuards,
  Request,
  UseInterceptors,
  UploadedFile,
  Res,
  ParseIntPipe,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Request as ExpressRequest, Response } from 'express';
import * as fs from 'fs';
import { ArchiveReportService } from './archive-report.service';
import { ArchiveService } from './archive.service';
import {
  UpsertProfileDto,
  CreateEnrollmentDto,
  UpdateEnrollmentDto,
  CreateExamScoreDto,
  UpdateExamScoreDto,
  CreateLearningRecordDto,
  UpdateLearningRecordDto,
  UpsertResultDto,
} from './dto/archive.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { OperationLogsService } from '../operation-logs/operation-logs.service';
import { extractRequestInfo } from '../common/request-utils';
import { RequirePermission } from '../auth/decorators/permission.decorator';

interface AuthenticatedRequest extends ExpressRequest {
  user?: { id: number; username?: string };
}

@UseGuards(JwtAuthGuard)
@Controller('archive')
export class ArchiveController {
  constructor(
    private readonly archiveService: ArchiveService,
    private readonly logService: OperationLogsService,
    private readonly reportService: ArchiveReportService,
  ) {}

  @Get(':studentId')
  @RequirePermission('student:view')
  async getProfile(@Param('studentId', ParseIntPipe) studentId: number, @Request() req: AuthenticatedRequest) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.getProfile(studentId);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '查看档案',
      targetId: studentId,
      targetType: 'archive',
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Put(':studentId/profile')
  @RequirePermission('student:edit')
  async upsertProfile(
    @Param('studentId', ParseIntPipe) studentId: number,
    @Body() dto: UpsertProfileDto,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.upsertProfile(studentId, dto);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '更新档案信息',
      targetId: studentId,
      targetType: 'student_profile',
      detail: JSON.stringify(dto),
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Post(':studentId/enrollments')
  @RequirePermission('student:edit')
  async addEnrollment(
    @Param('studentId', ParseIntPipe) studentId: number,
    @Body() dto: CreateEnrollmentDto,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.addEnrollment(studentId, dto);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '添加报名记录',
      targetId: result.id,
      targetType: 'student_enrollment',
      detail: `${dto.courseCategory} - ${dto.classType}`,
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Put('enrollments/:id')
  @RequirePermission('student:edit')
  async updateEnrollment(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: UpdateEnrollmentDto,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.updateEnrollment(id, dto);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '编辑报名记录',
      targetId: id,
      targetType: 'student_enrollment',
      detail: JSON.stringify(dto),
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Delete('enrollments/:id')
  @RequirePermission('student:edit')
  async deleteEnrollment(@Param('id', ParseIntPipe) id: number, @Request() req: AuthenticatedRequest) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.deleteEnrollment(id);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '归档报名记录',
      targetId: id,
      targetType: 'student_enrollment',
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Post(':studentId/exam-scores')
  @RequirePermission('student:edit')
  async addExamScore(
    @Param('studentId', ParseIntPipe) studentId: number,
    @Body() dto: CreateExamScoreDto,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.addExamScore(studentId, dto);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '添加考试成绩',
      targetId: result.id,
      targetType: 'exam_score',
      detail: `${dto.examType} - ${dto.subject}: ${dto.score}`,
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Put('exam-scores/:id')
  @RequirePermission('student:edit')
  async updateExamScore(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: UpdateExamScoreDto,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.updateExamScore(id, dto);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '编辑考试成绩',
      targetId: id,
      targetType: 'exam_score',
      detail: JSON.stringify(dto),
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Delete('exam-scores/:id')
  @RequirePermission('student:edit')
  async deleteExamScore(@Param('id', ParseIntPipe) id: number, @Request() req: AuthenticatedRequest) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.deleteExamScore(id);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '归档考试成绩',
      targetId: id,
      targetType: 'exam_score',
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Post(':studentId/learning-records')
  @RequirePermission('student:edit')
  async addLearningRecord(
    @Param('studentId', ParseIntPipe) studentId: number,
    @Body() dto: CreateLearningRecordDto,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.addLearningRecord(studentId, dto);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '添加学习记录',
      targetId: result.id,
      targetType: 'learning_record',
      detail: `${dto.recordType}: ${dto.content.substring(0, 50)}`,
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Put('learning-records/:id')
  @RequirePermission('student:edit')
  async updateLearningRecord(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: UpdateLearningRecordDto,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.updateLearningRecord(id, dto);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '编辑学习记录',
      targetId: id,
      targetType: 'learning_record',
      detail: JSON.stringify(dto),
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Delete('learning-records/:id')
  @RequirePermission('student:edit')
  async deleteLearningRecord(@Param('id', ParseIntPipe) id: number, @Request() req: AuthenticatedRequest) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.deleteLearningRecord(id);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '归档学习记录',
      targetId: id,
      targetType: 'learning_record',
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Put(':studentId/result')
  @RequirePermission('student:edit')
  async upsertResult(
    @Param('studentId', ParseIntPipe) studentId: number,
    @Body() dto: UpsertResultDto,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.upsertResult(studentId, dto);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '更新录取结果',
      targetId: studentId,
      targetType: 'result_archive',
      detail: JSON.stringify(dto),
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Post(':studentId/attachments')
  @RequirePermission('student:edit')
  @UseInterceptors(FileInterceptor('file'))
  async uploadAttachment(
    @Param('studentId', ParseIntPipe) studentId: number,
    @UploadedFile() file: Express.Multer.File,
    @Body('category') category: string,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.addAttachment(studentId, file, category || 'other');
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '上传附件',
      targetId: result.id,
      targetType: 'archive_attachment',
      detail: `${file.originalname} (${category || 'other'})`,
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Get(':studentId/attachments/:id')
  @RequirePermission('student:view')
  async downloadAttachment(
    @Param('studentId', ParseIntPipe) studentId: number,
    @Param('id', ParseIntPipe) id: number,
    @Res() res: Response,
  ) {
    const { fullPath, fileName, mimeType } = await this.archiveService.getAttachmentFile(
      studentId,
      id,
    );
    res.setHeader('Content-Type', mimeType);
    res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(fileName)}"`);
    const stream = fs.createReadStream(fullPath);
    stream.pipe(res);
  }

  @Delete('attachments/:id')
  @RequirePermission('student:edit')
  async deleteAttachment(@Param('id', ParseIntPipe) id: number, @Request() req: AuthenticatedRequest) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.archiveService.deleteAttachment(id);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '学生档案',
      action: '归档附件',
      targetId: id,
      targetType: 'archive_attachment',
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Get(':studentId/report-html')
  @RequirePermission('student:view')
  async generateReportHtml(
    @Param('studentId', ParseIntPipe) studentId: number,
    @Request() req: AuthenticatedRequest,
  ) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: 'archive',
      action: 'generate_report_html',
      targetId: studentId,
      targetType: 'student',
      ipAddress,
      userAgent,
    });
    const html = await this.reportService.generateReportHtml(studentId);
    return { html };
  }
}
