import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';
import { diskStorage } from 'multer';
import * as fs from 'fs';
import { generateSlug } from '../slug/slug-url';
import { BadRequestException } from '@nestjs/common';

const createFolderIfNotExist = (path) => {
  if (!fs.existsSync(path)) {
    fs.mkdirSync(path, { recursive: true, mode: 0o775 });
  }
};

export const imageConfig: MulterOptions = {
  storage: diskStorage({
    destination: (req, file, cb) => {
      let uploadPath;
      switch (file.fieldname) {
        case 'group_icon':
          uploadPath = './public/uploads/group-icons';
          break;
        case 'banner':
          uploadPath = './public/uploads/offer-banners';
          break;
        case 'profile_picture':
          uploadPath = './public/uploads/app-users/profile-picture';
          break;
        case 'media':
          uploadPath = './public/uploads/category';
          break;
        default:
          return cb(new Error('Unknown field'), null);
      }
      createFolderIfNotExist(uploadPath);
      cb(null, uploadPath);
    },
    filename: (req, file, cb) => {
      const timestamp = Date.now();
      const originalFilename = file.originalname;
      const fileExtension = originalFilename.split('.').pop();
      const fileNameWithoutExtension = originalFilename.replace(
        `.${fileExtension}`,
        '',
      );
      const slugifyFilename = generateSlug(fileNameWithoutExtension);
      const newFilename = `${slugifyFilename}-${timestamp}.${fileExtension}`;

      return cb(null, newFilename);
    },
  }),

  fileFilter: (req, file, cb) => {
    if (!file.originalname.match(/\.(jpg|jpeg|png|webp)$/)) {
      return cb(
        new BadRequestException({
          status: false,
          code: 400,
          message:
            'Only following file formats are allowed (jpg,jpeg,png,webp).',
        }),
        false,
      );
    }
    cb(null, true);
  },
};

export const tipsConfig: MulterOptions = {
  storage: diskStorage({
    destination: (req, file, cb) => {
      const uploadPath = './public/uploads/tips';
      createFolderIfNotExist(uploadPath);
      cb(null, uploadPath);
    },
    filename: (req, file, cb) => {
      const timestamp = Date.now();
      const originalFilename = file.originalname;
      const fileExtension = originalFilename.split('.').pop();
      const fileNameWithoutExtension = originalFilename.replace(
        `.${fileExtension}`,
        '',
      );
      const slugifyFilename = generateSlug(fileNameWithoutExtension);
      const newFilename = `${slugifyFilename}-${timestamp}.${fileExtension}`;

      return cb(null, newFilename);
    },
  }),

  fileFilter: async (req, file, cb) => {
    try {
      const allowedImageExtensions = ['jpg', 'jpeg', 'png', 'webp'];
      const allowedVideoExtensions = [
        'mp4',
        'mkv',
        'mov',
        'quicktime',
        'x-matroska',
      ];

      const fileExtension = file.originalname.split('.').pop().toLowerCase();
      const fileType = allowedImageExtensions.includes(fileExtension)
        ? 'image'
        : allowedVideoExtensions.includes(fileExtension)
        ? 'video'
        : null;

      if (!fileType) {
        return cb(
          new BadRequestException({
            status: false,
            code: 400,
            message:
              'Only image (jpg, jpeg, png, webp) and video (mp4, mkv, mov) file formats are allowed.',
            data: [],
          }),
          false,
        );
      }

      cb(null, true);
    } catch (error) {
      cb(
        new BadRequestException({
          status: false,
          code: 400,
          message: 'Error processing the file.',
          data: [],
        }),
        false,
      );
    }
  },
};

export const profilePictureConfig: MulterOptions = {
  storage: diskStorage({
    destination: (req, file, cb) => {
      const uploadPath = './public/uploads/profile-picture';
      createFolderIfNotExist(uploadPath);
      cb(null, uploadPath);
    },
    filename: (req, file, cb) => {
      const timestamp = Date.now();
      const originalFilename = file.originalname;
      const fileExtension = originalFilename.split('.').pop();
      const fileNameWithoutExtension = originalFilename.replace(
        `.${fileExtension}`,
        '',
      );
      const slugifyFilename = generateSlug(fileNameWithoutExtension);
      const newFilename = `${slugifyFilename}-${timestamp}.${fileExtension}`;

      return cb(null, newFilename);
    },
  }),
  limits: {
    fileSize: 20 * 1024 * 1024,
  },
  fileFilter: (req, file, cb) => {
    if (!file.originalname.match(/\.(jpg|jpeg|png|webp)$/)) {
      return cb(
        new BadRequestException({
          statusCode: 400,
          message:
            'Only following file formats are allowed (jpg,jpeg,png,webp).',
        }),
        false,
      );
    }
    cb(null, true);
  },
};

export const newsImagesConfig: MulterOptions = {
  storage: diskStorage({
    destination: (req, file, cb) => {
      const uploadPath = './public/uploads/news-images';
      createFolderIfNotExist(uploadPath);
      cb(null, uploadPath);
    },
    filename: (req, file, cb) => {
      const timestamp = Date.now();
      const originalFilename = file.originalname;
      const fileExtension = originalFilename.split('.').pop();
      const fileNameWithoutExtension = originalFilename.replace(
        `.${fileExtension}`,
        '',
      );
      const slugifyFilename = generateSlug(fileNameWithoutExtension);
      const newFilename = `${slugifyFilename}-${timestamp}.${fileExtension}`;

      return cb(null, newFilename);
    },
  }),

  fileFilter: async (req, file, cb) => {
    try {
      const allowedImageExtensions = ['jpg', 'jpeg', 'png', 'webp'];
      const allowedVideoExtensions = [
        'mp4',
        'mkv',
        'mov',
        'quicktime',
        'x-matroska',
      ];

      const fileExtension = file.originalname.split('.').pop().toLowerCase();
      const fileType = allowedImageExtensions.includes(fileExtension)
        ? 'image'
        : allowedVideoExtensions.includes(fileExtension)
        ? 'video'
        : null;

      if (!fileType) {
        return cb(
          new BadRequestException({
            status: false,
            code: 400,
            message:
              'Only image (jpg, jpeg, png, webp) and video (mp4, mkv, mov) file formats are allowed.',
            data: [],
          }),
          false,
        );
      }

      cb(null, true);
    } catch (error) {
      cb(
        new BadRequestException({
          status: false,
          code: 400,
          message: 'Error processing the file.',
          data: [],
        }),
        false,
      );
    }
  },
};

export const challengesImagesConfig: MulterOptions = {
  storage: diskStorage({
    destination: (req, file, cb) => {
      const uploadPath = './public/uploads/challenges-images';
      createFolderIfNotExist(uploadPath);
      cb(null, uploadPath);
    },
    filename: (req, file, cb) => {
      const timestamp = Date.now();
      const originalFilename = file.originalname;
      const fileExtension = originalFilename.split('.').pop();
      const fileNameWithoutExtension = originalFilename.replace(
        `.${fileExtension}`,
        '',
      );
      const slugifyFilename = generateSlug(fileNameWithoutExtension);
      const newFilename = `${slugifyFilename}-${timestamp}.${fileExtension}`;

      return cb(null, newFilename);
    },
  }),

  fileFilter: async (req, file, cb) => {
    try {
      const allowedImageExtensions = ['jpg', 'jpeg', 'png', 'webp'];
      const allowedVideoExtensions = [
        'mp4',
        'mkv',
        'mov',
        'quicktime',
        'x-matroska',
      ];

      const fileExtension = file.originalname.split('.').pop().toLowerCase();
      const fileType = allowedImageExtensions.includes(fileExtension)
        ? 'image'
        : allowedVideoExtensions.includes(fileExtension)
        ? 'video'
        : null;

      if (!fileType) {
        return cb(
          new BadRequestException({
            status: false,
            code: 400,
            message:
              'Only image (jpg, jpeg, png, webp) and video (mp4, mkv, mov) file formats are allowed.',
            data: [],
          }),
          false,
        );
      }

      cb(null, true);
    } catch (error) {
      cb(
        new BadRequestException({
          status: false,
          code: 400,
          message: 'Error processing the file.',
          data: [],
        }),
        false,
      );
    }
  },
};
