import {
  Body,
  Controller,
  Delete,
  Get,
  Post,
  Put,
  Query,
  Res,
  UploadedFiles,
  UseInterceptors,
} from '@nestjs/common';
import { FilesInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { Response } from 'express';
import { mkdirSync } from 'fs';
import { join } from 'path';
import { FileManagerService } from './file-manager.service';

type UploadedManagedFile = {
  originalname: string;
  mimetype: string;
  buffer?: Buffer;
  path?: string;
  size: number;
};

const uploadTmpDir = join(process.cwd(), 'storage', 'file-manager-upload-tmp');

@Controller('file-manager')
export class FileManagerController {
  constructor(private readonly fileManagerService: FileManagerService) {}

  @Get()
  list(
    @Query('path') path = '',
    @Query('limit') limit = '18',
    @Query('offset') offset = '0',
  ) {
    return this.fileManagerService.list(path, Number(limit), Number(offset));
  }

  @Post('folders')
  createFolder(@Body() body: { path?: string; name?: string }) {
    return this.fileManagerService.createFolder(body.path || '', body.name || '');
  }

  @Post('files')
  createFile(@Body() body: { path?: string; name?: string; content?: string }) {
    return this.fileManagerService.createFile(body.path || '', body.name || '', body.content || '');
  }

  @Put('rename')
  rename(@Body() body: { path?: string; name?: string }) {
    return this.fileManagerService.rename(body.path || '', body.name || '');
  }

  @Post('move')
  move(@Body() body: { paths?: string[]; destinationPath?: string }) {
    return this.fileManagerService.move(body.paths || [], body.destinationPath || '');
  }

  @Delete()
  remove(@Query('path') path = '') {
    return this.fileManagerService.remove(path);
  }

  @Post('upload')
  @UseInterceptors(
    FilesInterceptor('files', 20, {
      storage: diskStorage({
        destination: (_request, _file, callback) => {
          mkdirSync(uploadTmpDir, { recursive: true });
          callback(null, uploadTmpDir);
        },
        filename: (_request, file, callback) => {
          const safeSuffix = file.originalname.replace(/[^\w.-]+/g, '_').slice(-80) || 'upload';
          callback(null, `${Date.now()}-${Math.random().toString(36).slice(2)}-${safeSuffix}`);
        },
      }),
      limits: {
        fileSize: 2 * 1024 * 1024 * 1024,
        files: 20,
      },
    }),
  )
  upload(
    @UploadedFiles()
    files: UploadedManagedFile[],
    @Body('path') path = '',
  ) {
    return this.fileManagerService.upload(path, files);
  }

  @Post('unzip')
  unzip(@Body() body: { path?: string; destinationName?: string }) {
    return this.fileManagerService.unzip(body.path || '', body.destinationName || '');
  }

  @Get('content')
  async content(
    @Query('path') path = '',
    @Query('download') download = '',
    @Res() response: Response,
  ) {
    const file = await this.fileManagerService.resolveFile(path);
    if (download === '1') {
      return response.download(file.fullPath, file.name);
    }
    return response.sendFile(file.fullPath);
  }
}
