import multer from "multer";
import crypto from "crypto";
import path from "path";
import fs from "fs";
import response from "../../response.js";

const memoryStorage = multer.memoryStorage();

const fileFilter = (req, file, cb) => {
  const ext = path.extname(file.originalname).toLowerCase();

  switch (file.fieldname) {
    case "AUDIO":
      if (ext === ".mp3") {
        cb(null, true);
      } else {
        cb(
          new Error(
            "Invalid file type, only .mp3 files are allowed for audio!"
          ),
          false
        );
      }
      break;

    case "IMAGE":
      if (ext === ".jpg" || ext === ".jpeg" || ext === ".png") {
        cb(null, true);
      } else {
        cb(
          new Error(
            "Invalid file type, only .jpg, .jpeg, and .png files are allowed for image!"
          ),
          false
        );
      }
      break;

    default:
      cb(new Error("Invalid file type!"), false);
  }
};

const upload = multer({
  storage: memoryStorage,
  fileFilter,
  limits: {
    fileSize: 100 * 1024 * 1024,
  },
}).fields([
  { name: "AUDIO", maxCount: 1 },
  { name: "IMAGE", maxCount: 1 },
]);

const handleUpload = (req, res, next) => {
  upload(req, res, (err) => {
    if (err) {
      return response(400, null, err.message, res);
    }

    const files = req.files;
    const AUDIO = files?.AUDIO ? files.AUDIO[0] : null;
    const IMAGE = files?.IMAGE ? files.IMAGE[0] : null;

    try {
      let validFiles = true;
      let errorMessages = [];

      if (AUDIO && AUDIO.size > 10 * 1024 * 1024) {
        validFiles = false;
        AUDIO.buffer = null;
        errorMessages.push("Audio file exceeds the size limit of 10MB");
      }

      if (IMAGE && IMAGE.size > 5 * 1024 * 1024) {
        validFiles = false;
        IMAGE.buffer = null;
        errorMessages.push("Image file exceeds the size limit of 5MB");
      }

      if (validFiles) {
        req.filesToSave = { AUDIO, IMAGE };
        next();
      } else {
        clearFileBuffers({ AUDIO, IMAGE });
        return response(400, null, errorMessages.join("; "), res);
      }
    } catch (error) {
      console.log(error);
      clearFileBuffers({ AUDIO, IMAGE });
      return response(500, null, "Internal Server Error", res);
    }
  });
};

export const clearFileBuffers = (files) => {
  for (const file of Object.values(files)) {
    if (file && file.buffer) {
      file.buffer = null;
    }
  }
};

export const generateHash = (sectionId, topicId, filename, bufferLength) => {
  return crypto
    .createHash("md5")
    .update(sectionId + topicId + filename + bufferLength)
    .digest("hex");
};

export const saveFileToDisk = (file, type, topicId, sectionId, levelId) => {
  const ext = path.extname(file.originalname);
  const hash = generateHash(sectionId, topicId, file.originalname, file.buffer.length);
  const filename = `${type}-${levelId}-${hash}${ext}`;

  let folderPath;
  switch (type) {
    case "AUDIO":
      folderPath = path.join("public/uploads/level/audio");
      break;
    case "IMAGE":
      folderPath = path.join("public/uploads/level/image");
      break;
    default:
      folderPath = path.join("public/uploads/level");
  }

  if (!fs.existsSync(folderPath)) {
    fs.mkdirSync(folderPath, { recursive: true });
  }

  const filepath = path.join(folderPath, filename);
  fs.writeFileSync(filepath, file.buffer);
  return filename;
};

export default handleUpload;
