import {
  Controller,
  Get,
  Post,
  Query,
  Body,
  Res,
  UseGuards,
  UseInterceptors,
  UploadedFile,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
import { Response } from 'express';
import { CurrentTenant } from '../../common/decorators/current-tenant.decorator';
import { RequirePermission } from '../../common/decorators/require-permission.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { PermissionsGuard } from '../../common/guards/permissions.guard';
import { FilesService } from './files.service';

@ApiTags('Files')
@ApiBearerAuth()
@Controller('files')
@UseGuards(JwtAuthGuard, PermissionsGuard)
export class FilesController {
  constructor(private readonly filesService: FilesService) {}

  // VueFinder GET operations: ?q=index (list), ?q=search, ?q=preview, ?q=download
  @Get()
  @RequirePermission('files.view')
  async handleGet(
    @CurrentTenant() licenseId: string,
    @Query('q') operation: string,
    @Query('path') path: string,
    @Query('filter') filter: string,
    @Res({ passthrough: true }) res: Response,
  ) {
    switch (operation) {
      case 'index':
      case undefined:
      case '':
        return this.filesService.list(licenseId, path || 'server://');
      case 'search':
        return this.filesService.search(licenseId, path || 'server://', filter);
      case 'preview':
        return this.filesService.preview(licenseId, path);
      case 'download': {
        const result = await this.filesService.download(licenseId, path);
        res.setHeader('Content-Type', 'application/octet-stream');
        res.setHeader(
          'Content-Disposition',
          `attachment; filename="${result.filename}"`,
        );
        res.send(result.content);
        return;
      }
      default:
        throw new HttpException(
          `Unknown operation: ${operation}`,
          HttpStatus.BAD_REQUEST,
        );
    }
  }

  // VueFinder POST operations: ?q=delete, rename, move, copy, new-folder, new-file, save, upload
  @Post()
  @RequirePermission('files.manage')
  @UseInterceptors(FileInterceptor('upload'))
  async handlePost(
    @CurrentTenant() licenseId: string,
    @Query('q') operation: string,
    @Body() body: Record<string, any>,
    @UploadedFile() file?: Express.Multer.File,
  ) {
    switch (operation) {
      case 'delete':
        return this.filesService.delete(licenseId, body.path, body.items);
      case 'rename':
        return this.filesService.rename(
          licenseId,
          body.path,
          body.item,
          body.name,
        );
      case 'move':
        return this.filesService.move(
          licenseId,
          body.path,
          body.items,
          body.destination,
        );
      case 'copy':
        return this.filesService.copy(
          licenseId,
          body.path,
          body.items,
          body.destination,
        );
      case 'new-folder':
      case 'mkdir':
        return this.filesService.createFolder(licenseId, body.path, body.name);
      case 'new-file':
      case 'newfile':
        return this.filesService.createFile(licenseId, body.path, body.name);
      case 'save':
        return this.filesService.save(licenseId, body.path, body.content);
      case 'upload':
        if (!file) {
          throw new HttpException('No file provided', HttpStatus.BAD_REQUEST);
        }
        return this.filesService.upload(licenseId, body.path, file);
      default:
        throw new HttpException(
          `Unknown operation: ${operation}`,
          HttpStatus.BAD_REQUEST,
        );
    }
  }
}
