import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  UseGuards,
  Request,
  Res,
  UseInterceptors,
  UploadedFile,
  BadRequestException,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Response } from 'express';
import * as fs from 'fs';
import { ClassroomRentalsService } from './classroom-rentals.service';
import { CreateRentalDto, UpdateRentalDto } from './dto/rental.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';

@UseGuards(JwtAuthGuard)
@Controller('classroom-rentals')
export class ClassroomRentalsController {
  constructor(
    private service: ClassroomRentalsService,
    private logService: OperationLogsService,
  ) {}

  @Get()
  @RequirePermission('rental:view')
  findAll(
    @Query('classroomId') classroomId?: string,
    @Query('lesseeOrganizationId') lesseeOrganizationId?: string,
    @Query('month') month?: string,
    @Query('includeEnded') includeEnded?: string,
  ) {
    return this.service.findAll({
      classroomId: classroomId ? +classroomId : undefined,
      lesseeOrganizationId: lesseeOrganizationId ? +lesseeOrganizationId : undefined,
      month,
      includeEnded: includeEnded === 'true',
    });
  }

  @Get('schedule')
  @RequirePermission('rental:view')
  getSchedule(@Query('year') year?: string, @Query('month') month?: string) {
    const now = new Date();
    const y = year ? +year : now.getFullYear();
    const m = month ? +month : now.getMonth() + 1;
    if (m < 1 || m > 12) throw new BadRequestException('月份必须在 1-12 之间');
    return this.service.getSchedule(y, m);
  }

  @Get('unavailable-dates')
  @RequirePermission('rental:view')
  getUnavailableDates(
    @Query('classroomId') classroomId?: string,
    @Query('year') year?: string,
    @Query('month') month?: string,
    @Query('excludeId') excludeId?: string,
  ) {
    const parsedClassroomId = Number(classroomId);
    const parsedYear = Number(year);
    const parsedMonth = Number(month);
    if (!Number.isInteger(parsedClassroomId) || parsedClassroomId <= 0) {
      throw new BadRequestException('请选择有效教室');
    }
    if (!Number.isInteger(parsedYear) || parsedYear < 2000 || parsedYear > 2100) {
      throw new BadRequestException('年份不合法');
    }
    if (!Number.isInteger(parsedMonth) || parsedMonth < 1 || parsedMonth > 12) {
      throw new BadRequestException('月份必须在 1-12 之间');
    }
    const parsedExcludeId = excludeId === undefined ? undefined : Number(excludeId);
    if (
      parsedExcludeId !== undefined &&
      (!Number.isInteger(parsedExcludeId) || parsedExcludeId <= 0)
    ) {
      throw new BadRequestException('排除的租赁订单不合法');
    }
    return this.service.getUnavailableDates(
      parsedClassroomId,
      parsedYear,
      parsedMonth,
      parsedExcludeId,
    );
  }

  @Get(':id')
  @RequirePermission('rental:view')
  findOne(@Param('id') id: string) {
    return this.service.findOne(+id);
  }

  @Post()
  @RequirePermission('rental:create')
  async create(@Body() dto: CreateRentalDto, @Request() req: any) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.service.create(dto, req.user?.id);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '教室租赁',
      action: '新增租赁',
      targetId: result.id,
      targetType: 'classroom-rental',
      detail: `教室${dto.classroomId} 承租机构${dto.lesseeOrganizationId} ${dto.startDate}~${dto.endDate}`,
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Put(':id')
  @RequirePermission('rental:edit')
  async update(@Param('id') id: string, @Body() dto: UpdateRentalDto, @Request() req: any) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.service.update(+id, dto);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '教室租赁',
      action: '编辑租赁',
      targetId: +id,
      targetType: 'classroom-rental',
      detail: JSON.stringify(dto),
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Put(':id/cancel')
  @RequirePermission('rental:edit')
  async cancel(@Param('id') id: string, @Request() req: any) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.service.cancel(+id);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '教室租赁',
      action: '取消租赁',
      targetId: +id,
      targetType: 'classroom-rental',
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Put(':id/end')
  @RequirePermission('rental:edit')
  async end(@Param('id') id: string, @Request() req: any) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.service.end(+id);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '教室租赁',
      action: '结束租赁',
      targetId: +id,
      targetType: 'classroom-rental',
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Delete(':id')
  @RequirePermission('rental:delete')
  async remove(@Param('id') id: string, @Request() req: any) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.service.remove(+id);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '教室租赁',
      action: '归档租赁',
      targetId: +id,
      targetType: 'classroom-rental',
      ipAddress,
      userAgent,
    });
    return result;
  }

  // 合同上传：multer 限制 10MB + 仅 PDF
  @Post(':id/contract')
  @RequirePermission('rental:edit')
  @UseInterceptors(
    FileInterceptor('file', {
      limits: { fileSize: 10 * 1024 * 1024 },
      fileFilter: (_req, file, cb) => {
        if (file.mimetype !== 'application/pdf') {
          return cb(new BadRequestException('仅支持 PDF 文件'), false);
        }
        cb(null, true);
      },
    }),
  )
  async uploadContract(
    @Param('id') id: string,
    @UploadedFile() file: Express.Multer.File,
    @Request() req: any,
  ) {
    if (!file) throw new BadRequestException('请上传合同文件');
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.service.attachContract(+id, file);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '教室租赁',
      action: '上传合同',
      targetId: +id,
      targetType: 'classroom-rental',
      detail: file.originalname,
      ipAddress,
      userAgent,
    });
    return result;
  }

  @Get(':id/contract')
  @RequirePermission('rental:view')
  async downloadContract(@Param('id') id: string, @Res() res: Response) {
    const { fullPath, originalName } = await this.service.getContractPath(+id);
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader(
      'Content-Disposition',
      `attachment; filename="${encodeURIComponent(originalName)}"`,
    );
    const stream = fs.createReadStream(fullPath);
    stream.pipe(res);
  }

  @Delete(':id/contract')
  @RequirePermission('rental:edit')
  async deleteContract(@Param('id') id: string, @Request() req: any) {
    const { ipAddress, userAgent } = extractRequestInfo(req);
    const result = await this.service.removeContract(+id);
    await this.logService.log({
      userId: req.user?.id,
      username: req.user?.username,
      module: '教室租赁',
      action: '移除合同',
      targetId: +id,
      targetType: 'classroom-rental',
      ipAddress,
      userAgent,
    });
    return result;
  }
}
