import multer from 'multer';
import path from 'path';
import fs from 'fs';
import { Request, Response, NextFunction } from 'express';
import { config } from '../config/env';
import { logger } from '../utils/logger';

// Use temporary directory for file uploads (files will be immediately moved to GCS)
const uploadDir = '/tmp/uploads';
if (!fs.existsSync(uploadDir)) {
  fs.mkdirSync(uploadDir, { recursive: true });
}

// File filter function
const fileFilter = (req: Request, file: any, cb: multer.FileFilterCallback) => {
  console.log('🔍 ===== FILE FILTER CALLED =====');
  console.log('🔍 File originalname:', file.originalname);
  console.log('🔍 File mimetype:', file.mimetype);
  console.log('🔍 File size:', file.size);
  console.log('🔍 File encoding:', file.encoding);
  console.log('🔍 File fieldname:', file.fieldname);
  console.log('🔍 Request Content-Type:', req.get('Content-Type'));
  console.log('🔍 Request Content-Length:', req.get('Content-Length'));
  console.log('🔍 ===========================');
  
  // Check file type - allow PDF and text files for testing
  const allowedTypes = ['application/pdf', 'text/plain', 'text/html'];
  if (!allowedTypes.includes(file.mimetype)) {
    const error = new Error(`File type ${file.mimetype} is not allowed. Only PDF and text files are accepted.`);
    console.log('❌ File rejected - invalid type:', file.mimetype);
    logger.warn(`File upload rejected - invalid type: ${file.mimetype}`, {
      originalName: file.originalname,
      size: file.size,
      ip: req.ip,
    });
    return cb(error);
  }

  // Check file extension - allow PDF and text extensions for testing
  const ext = path.extname(file.originalname).toLowerCase();
  if (!['.pdf', '.txt', '.html'].includes(ext)) {
    const error = new Error(`File extension ${ext} is not allowed. Only .pdf, .txt, and .html files are accepted.`);
    console.log('❌ File rejected - invalid extension:', ext);
    logger.warn(`File upload rejected - invalid extension: ${ext}`, {
      originalName: file.originalname,
      size: file.size,
      ip: req.ip,
    });
    return cb(error);
  }

  console.log('✅ File accepted:', file.originalname);
  logger.info(`File upload accepted: ${file.originalname}`, {
    originalName: file.originalname,
    size: file.size,
    mimetype: file.mimetype,
    ip: req.ip,
  });
  cb(null, true);
};

// Storage configuration - use memory storage for immediate GCS upload
const storage = multer.memoryStorage();

// Create multer instance
const upload = multer({
  storage,
  fileFilter,
  limits: {
    fileSize: config.upload.maxFileSize, // 100MB default
    files: 1, // Only allow 1 file per request
  },
});

// Error handling middleware for multer
export const handleUploadError = (error: any, req: Request, res: Response, next: NextFunction): void => {
  console.log('🚨 =============================');
  console.log('🚨 UPLOAD ERROR HANDLER CALLED');
  console.log('🚨 Error type:', error?.constructor?.name);
  console.log('🚨 Error message:', error?.message);
  console.log('🚨 Error code:', error?.code);
  console.log('🚨 Is MulterError:', error instanceof multer.MulterError);
  console.log('🚨 =============================');
  
  if (error instanceof multer.MulterError) {
    logger.error('Multer error during file upload:', {
      error: error.message,
      code: error.code,
      field: error.field,
      originalName: req.file?.originalname,
      ip: req.ip,
    });

    switch (error.code) {
      case 'LIMIT_FILE_SIZE':
        res.status(400).json({
          success: false,
          error: 'File too large',
          message: `File size must be less than ${config.upload.maxFileSize / (1024 * 1024)}MB`,
        });
        return;
      case 'LIMIT_FILE_COUNT':
        res.status(400).json({
          success: false,
          error: 'Too many files',
          message: 'Only one file can be uploaded at a time',
        });
        return;
      case 'LIMIT_UNEXPECTED_FILE':
        res.status(400).json({
          success: false,
          error: 'Unexpected file field',
          message: 'File must be uploaded using the correct field name',
        });
        return;
      default:
        res.status(400).json({
          success: false,
          error: 'File upload error',
          message: error.message,
        });
        return;
    }
  }

  if (error) {
    logger.error('File upload error:', {
      error: error.message,
      originalName: req.file?.originalname,
      ip: req.ip,
    });

    res.status(400).json({
      success: false,
      error: 'File upload failed',
      message: error.message,
    });
    return;
  }

  next();
};

// Main upload middleware with timeout handling
export const uploadMiddleware = (req: Request, res: Response, next: NextFunction) => {
  console.log('📤 =============================');
  console.log('📤 UPLOAD MIDDLEWARE CALLED');
  console.log('📤 Request method:', req.method);
  console.log('📤 Request URL:', req.url);
  console.log('📤 Content-Type:', req.get('Content-Type'));
  console.log('📤 Content-Length:', req.get('Content-Length'));
  console.log('📤 User-Agent:', req.get('User-Agent'));
  console.log('📤 =============================');
  
  // Set a timeout for the upload
  const uploadTimeout = setTimeout(() => {
    logger.error('Upload timeout for request:', {
      ip: req.ip,
      userAgent: req.get('User-Agent'),
    });
    res.status(408).json({
      success: false,
      error: 'Upload timeout',
      message: 'Upload took too long to complete',
    });
  }, 300000); // 5 minutes timeout

  // Clear timeout on successful upload
  const originalNext = next;
  next = (err?: any) => {
    clearTimeout(uploadTimeout);
    if (err) {
      console.log('❌ Upload middleware error:', err);
      console.log('❌ Error details:', {
        name: err.name,
        message: err.message,
        code: err.code,
        stack: err.stack?.split('\n')[0]
      });
    } else {
      console.log('✅ Upload middleware completed successfully');
      console.log('✅ File after multer processing:', {
        hasFile: !!req.file,
        filename: req.file?.originalname,
        size: req.file?.size,
        mimetype: req.file?.mimetype
      });
    }
    originalNext(err);
  };

  console.log('🔄 Calling multer.single("document")...');
  upload.single('document')(req, res, next);
};

// Combined middleware for file uploads
export const handleFileUpload = [
  uploadMiddleware,
  handleUploadError,
];

// Utility function to get file info from memory buffer
export const getFileInfo = (file: any) => {
  return {
    originalName: file.originalname,
    filename: file.originalname, // Use original name since we're not saving to disk
    buffer: file.buffer, // File buffer for GCS upload
    size: file.size,
    mimetype: file.mimetype,
    uploadedAt: new Date(),
  };
}; 