import { Controller, Post, Logger, BadRequestException, UploadedFile, UseInterceptors, Res, Body } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { TxtImportService } from './txt-import.service';
import { ApiTags, ApiOperation, ApiResponse, ApiConsumes, ApiBody } from '@nestjs/swagger';
import { diskStorage } from 'multer';
import { extname } from 'path';
import * as fs from 'fs';
import { Response } from 'express';
import { ImportCSVService } from '../csv-import/csv-import.service';

@Controller({ path: 'txt-import', version: '1' })
@ApiTags('TXT Import')
export class TxtImportController {
  private readonly logger = new Logger(TxtImportController.name);

  constructor(
    private readonly txtImportService: TxtImportService,
    private readonly csvImportService: ImportCSVService,
  ) {}

  @Post('breach-data')
  @ApiOperation({ summary: 'Upload breach data TXT file for import' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    description: 'TXT file to be uploaded',
    type: 'string',
    schema: {
      type: 'object',
      properties: {
        file: {
          type: 'string',
          format: 'binary',
        },
        fileType: {
          type: 'string',
          enum: ['txt', 'csv'],
          description: 'Type of the file being uploaded',
        },
        passwordColumnName: {
          type: 'string',
          description: 'Name of the column containing passwords (if applicable)',
        },
      },
      required: ['file', 'fileType'],
    },
  })
  @ApiResponse({ status: 200, description: 'File uploaded successfully, import queued' })
  @ApiResponse({ status: 400, description: 'Invalid file or format' })
  @UseInterceptors(
    FileInterceptor('file', {
      storage: diskStorage({
        destination: './uploads',
        filename: (req, file, cb) => {
          const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
          const fileExt = extname(file.originalname);
          cb(null, `breach-data-${uniqueSuffix}${fileExt}`);
        },
      }),
      fileFilter: (req, file, cb) => {
        const validMimeTypes = ['text/plain', 'text/csv'];
        const validExtensions = ['.txt', '.csv'];
        const fileExt = extname(file.originalname).toLowerCase();

        if (!validMimeTypes.includes(file.mimetype) && !validExtensions.some(ext => fileExt.endsWith(ext))) {
          return cb(new BadRequestException('Only TXT or CSV files are allowed'), false);
        }

        if (file.size > 10 * 1024 * 1024 * 1024) {
          // 5GB limit
          return cb(new BadRequestException('File size exceeds 5GB limit'), false);
        }

        cb(null, true);
      },
      limits: {
        fileSize: 10 * 1024 * 1024 * 1024, // 10GB limit
        files: 1,
      },
    }),
  )
  async uploadBreachData(@UploadedFile() file: Express.Multer.File, @Body() body: any, @Res() res: Response) {
    const { fileType, passwordColumnName, sourceColumnName } = body;
    if (!file) {
      throw new BadRequestException('No file uploaded');
    }

    if (!fileType || !['txt', 'csv'].includes(fileType.toLowerCase())) {
      throw new BadRequestException('Invalid file type. Must be "txt" or "csv"');
    }

    const filePath = `./uploads/${file.filename}`;
    this.logger.log(`Received ${fileType} file: ${filePath}`);

    // Send immediate response
    res.status(200).json({
      message: 'File uploaded successfully, import queued',
      fileName: file.filename,
      originalName: file.originalname,
      size: file.size,
      fileType: fileType,
    });

    // Process file in background
    this.processFileInBackground(filePath, fileType.toLowerCase(), passwordColumnName, sourceColumnName);
  }

  private processFileInBackground(filePath: string, fileType: string, passwordColumnName: string, sourceColumnName: string): void {
    // Ensure uploads directory exists
    const uploadDir = './uploads';
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }

    setTimeout(async () => {
      try {
        this.logger.log(`Starting background import of ${fileType} file: ${filePath}`);

        let result;
        if (fileType === 'txt') {
          result = await this.txtImportService.importTxt(filePath, 1000, true);
        } else if (fileType === 'csv') {
          result = await this.csvImportService.importCSVPassword(filePath, 1000, true, passwordColumnName, sourceColumnName);
        }

        this.logger.log(`Background import completed. Processed: ${result.totalProcessed}, Saved: ${result.totalSaved}`);
      } catch (err) {
        this.logger.error(`Background import failed: ${err.message}`);

        // Attempt to clean up the file if import failed
        try {
          if (fs.existsSync(filePath)) {
            fs.unlinkSync(filePath);
            this.logger.log(`Cleaned up file after failed import: ${filePath}`);
          }
        } catch (cleanupErr) {
          this.logger.error(`Failed to clean up file: ${cleanupErr.message}`);
        }
      }
    }, 100);
  }
}
