import multer, { FileFilterCallback } from 'multer';
import path from 'path';
import fs from 'fs';
import { Request, Response, NextFunction } from 'express';
import { v4 as uuidv4 } from 'uuid';

// Create uploads directory if it doesn't exist
const uploadDir = process.env.UPLOAD_DIR || './uploads';
const documentsDir = path.join(uploadDir, 'documents');
const profilesDir = path.join(uploadDir, 'profiles');
const tempDir = path.join(uploadDir, 'temp');

[uploadDir, documentsDir, profilesDir, tempDir].forEach(dir => {
    if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
    }
});

// Storage configuration
const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        let folder = documentsDir;

        if (req.body.uploadType === 'profile') {
            folder = profilesDir;
        } else if (req.body.uploadType === 'temp') {
            folder = tempDir;
        }

        cb(null, folder);
    },
    filename: (req, file, cb) => {
        const uniqueId = uuidv4();
        const ext = path.extname(file.originalname);
        const filename = `${uniqueId}${ext}`;
        cb(null, filename);
    }
});

// File filter
const fileFilter = (req: Request, file: Express.Multer.File, cb: FileFilterCallback) => {
    // Allowed file types
    const allowedTypes = [
        'application/pdf',
        'image/jpeg',
        'image/jpg',
        'image/png',
        'application/msword',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'application/vnd.ms-excel',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'application/vnd.ms-powerpoint',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation'
    ];

    if (allowedTypes.includes(file.mimetype)) {
        cb(null, true);
    } else {
        cb(new Error('Invalid file type. Only PDF, JPG, PNG, DOC, DOCX, XLS, XLSX allowed'));
    }
};

// Multer upload configuration
const upload = multer({
    storage: storage,
    limits: {
        fileSize: parseInt(process.env.MAX_FILE_SIZE || '') || 10 * 1024 * 1024 // 10MB default
    },
    fileFilter: fileFilter
});

// Single file upload
export const uploadSingle = upload.single('file');

/**
 * Only parse multipart when the client sends multipart/form-data.
 * Otherwise JSON bodies from express.json() are preserved — required for clearance APIs
 * called with application/json (e.g. trigger-resignation.js, axios without FormData).
 */
export const uploadSingleIfMultipart = (req: Request, res: Response, next: NextFunction) => {
    const ct = String(req.headers['content-type'] || '').toLowerCase();
    if (ct.includes('multipart/form-data')) {
        return uploadSingle(req, res, next);
    }
    next();
};

// Multiple files upload
export const uploadMultiple = upload.array('files', 10); // Max 10 files

/**
 * Only parse multipart with multiple files when the client sends multipart/form-data.
 * Otherwise JSON bodies from express.json() are preserved.
 */
export const uploadMultipleIfMultipart = (req: Request, res: Response, next: NextFunction) => {
    const ct = String(req.headers['content-type'] || '').toLowerCase();
    if (ct.includes('multipart/form-data')) {
        return uploadMultiple(req, res, next);
    }
    next();
};

// Error handler for multer
export const handleUploadError = (err: any, req: Request, res: Response, next: NextFunction) => {
    if (err instanceof multer.MulterError) {
        if (err.code === 'LIMIT_FILE_SIZE') {
            return res.status(400).json({
                success: false,
                message: 'File too large. Maximum size is 10MB'
            });
        }
        return res.status(400).json({
            success: false,
            message: `Upload error: ${err.message}`
        });
    } else if (err) {
        return res.status(400).json({
            success: false,
            message: err.message
        });
    }
    next();
};
