import multer from 'multer';
import { Request, RequestHandler } from 'express';
import { config } from '../config';
import { ValidationError } from './errorHandler';

/**
 * Allowed MIME types for different file categories
 */
export const ALLOWED_VIDEO_TYPES = [
    'video/mp4',
    'video/quicktime',
    'video/x-msvideo',
    'video/webm',
    'video/x-matroska',
];

export const ALLOWED_ATTACHMENT_TYPES = [
    // Documents
    'application/pdf',
    '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',
    // Text
    'text/plain',
    'text/csv',
    // Images
    'image/jpeg',
    'image/png',
    'image/gif',
    'image/webp',
    'image/svg+xml',
    // Archives
    'application/zip',
    'application/x-rar-compressed',
    'application/x-7z-compressed',
];

/**
 * Custom file filter for lesson uploads
 */
const fileFilter = (
    req: Request,
    file: Express.Multer.File,
    callback: multer.FileFilterCallback
) => {
    if (file.fieldname === 'video') {
        if (ALLOWED_VIDEO_TYPES.includes(file.mimetype)) {
            callback(null, true);
        } else {
            callback(new ValidationError(`Invalid video file type: ${file.mimetype}. Allowed types: ${ALLOWED_VIDEO_TYPES.join(', ')}`));
        }
    } else if (file.fieldname === 'attachments') {
        if (ALLOWED_ATTACHMENT_TYPES.includes(file.mimetype)) {
            callback(null, true);
        } else {
            callback(new ValidationError(`Invalid attachment file type: ${file.mimetype}. Allowed types: PDF, Word, Excel, PowerPoint, images, and archives`));
        }
    } else {
        callback(new ValidationError(`Unknown field: ${file.fieldname}`));
    }
};

/**
 * Multer configuration for lesson file uploads
 * Stores files in memory for direct upload to MinIO
 */
export const lessonUpload: RequestHandler = multer({
    storage: multer.memoryStorage(),
    limits: {
        fileSize: config.upload.maxVideoSize, // Max file size (500MB for videos)
        files: config.upload.maxAttachmentsPerLesson + 1, // +1 for video
    },
    fileFilter,
}).fields([
    { name: 'video', maxCount: 1 },
    { name: 'attachments', maxCount: config.upload.maxAttachmentsPerLesson },
]);

/**
 * Extended Request interface for uploaded files
 */
export interface LessonUploadRequest extends Request {
    files?: {
        video?: Express.Multer.File[];
        attachments?: Express.Multer.File[];
    };
}

/**
 * Validate total attachment size
 */
export function validateTotalAttachmentSize(
    files: Express.Multer.File[] | undefined
): void {
    if (!files) return;

    const totalSize = files.reduce((sum, file) => sum + file.size, 0);
    const maxTotalSize = config.upload.maxAttachmentSize * config.upload.maxAttachmentsPerLesson;

    if (totalSize > maxTotalSize) {
        throw new ValidationError(
            `Total attachment size (${(totalSize / 1024 / 1024).toFixed(2)} MB) exceeds maximum allowed (${(maxTotalSize / 1024 / 1024).toFixed(2)} MB)`
        );
    }
}

/**
 * Validate video file size
 */
export function validateVideoSize(file: Express.Multer.File | undefined): void {
    if (!file) return;

    if (file.size > config.upload.maxVideoSize) {
        throw new ValidationError(
            `Video file size (${(file.size / 1024 / 1024).toFixed(2)} MB) exceeds maximum allowed (${(config.upload.maxVideoSize / 1024 / 1024).toFixed(2)} MB)`
        );
    }
}
