import { Controller, Get, Post, Param, Delete, UseGuards, UploadedFile, UseInterceptors, Body, ForbiddenException, NotFoundException, Req, Res, ParseIntPipe } from '@nestjs/common';
import { FilesService } from './files.service';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname } from 'path';
import type { Response } from 'express';
import { PrismaService } from '../prisma/prisma.service';
import * as fs from 'fs';

@Controller('files')
@UseGuards(JwtAuthGuard)
export class FilesController {
  constructor(
    private readonly filesService: FilesService,
    private readonly prisma: PrismaService
  ) {}

  @Post('upload')
  @UseInterceptors(FileInterceptor('file', {
    storage: diskStorage({
      destination: './uploads',
      filename: (req, file, callback) => {
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
        const ext = extname(file.originalname);
        callback(null, `${uniqueSuffix}${ext}`);
      },
    }),
  }))
  async uploadFile(@UploadedFile() file: Express.Multer.File, @Body('timetableEntryId') timetableEntryId: string, @Req() req: any) {
    const user = req.user;
    const entryId = timetableEntryId ? parseInt(timetableEntryId) : undefined;

    if (!file) {
        throw new NotFoundException('No file uploaded');
    }

    try {
        if (entryId) {
            // Lesson Upload
            const lesson = await this.prisma.timetableEntry.findUnique({ where: { id: entryId } });
            if (!lesson) throw new NotFoundException('Lesson not found');

            if (user.role !== 'Lehrer') {
                // Student uploading to lesson
                if (!lesson.allowStudentUploads) {
                    throw new ForbiddenException('Uploads not allowed for this lesson');
                }
            }
        } else {
            // General Upload
            if (user.role !== 'Lehrer') {
                throw new ForbiddenException('Only teachers can upload general files');
            }
        }

        return await this.filesService.saveFile(file, user.id, entryId);
    } catch (error) {
        // Cleanup file if error
        if (file.path && fs.existsSync(file.path)) {
            fs.unlinkSync(file.path);
        }
        throw error;
    }
  }

  @Get()
  async findAllGeneral() {
      return this.filesService.findAllGeneral();
  }

  @Get('lesson/:id')
  async findByLesson(@Param('id', ParseIntPipe) id: number, @Req() req: any) {
      return this.filesService.findByLesson(id, req.user.id, req.user.role);
  }

  @Get('download/:id')
  async downloadFile(@Param('id', ParseIntPipe) id: number, @Res() res: Response) {
      const fileEntity = await this.filesService.getFileEntity(id);
      res.download(fileEntity.path, fileEntity.filename);
  }

  @Delete(':id')
  async deleteFile(@Param('id', ParseIntPipe) id: number, @Req() req: any) {
      return this.filesService.deleteFile(id, req.user.id, req.user.role);
  }
}