import response from "../../response.js";
import models from "../../models/index.js";
import {
  clearFileBuffers,
  saveFileToDisk,
} from "../../middlewares/Level/uploadLevel.js";
import fs from "fs";
import path from "path";
import {
  updateOtherLevelsRoutes,
  updateOtherLevelsRoutesOnDelete,
} from "../../middlewares/Level/checkLevel.js";

export const getLevels = async (req, res) => {
  try {
    const levels = await models.Level.findAll({
      where: {
        IS_DELETED: 0,
      },
      attributes: {
        exclude: [
          "ROUTE_1",
          "ROUTE_2",
          "ROUTE_3",
          "ROUTE_4",
          "ROUTE_5",
          "ROUTE_6",
        ],
      },
    });

    response(200, levels, "Success", res);
  } catch (error) {
    console.log(error);
    response(500, null, "Error retrieving levels data!", res);
  }
};

export const getLevelById = async (req, res) => {
  try {
    const { id } = req.params;

    const level = await models.Level.findByPk(id, {
      where: {
        IS_DELETED: 0,
      },
      attributes: {
        exclude: [
          "ROUTE_1",
          "ROUTE_2",
          "ROUTE_3",
          "ROUTE_4",
          "ROUTE_5",
          "ROUTE_6",
        ],
      },
      include: [
        {
          model: models.Topic,
          as: "levelTopic",
          attributes: ["NAME_TOPIC"],
          include: {
            model: models.Section,
            as: "topicSection",
            attributes: ["NAME_SECTION"],
          },
        },
      ],
    });

    if (!level) {
      return response(404, null, "Level not found", res);
    }

    const levelJSON = level.toJSON();
    const NAME_SECTION = levelJSON.levelTopic.topicSection.NAME_SECTION;
    const NAME_TOPIC = levelJSON.levelTopic.NAME_TOPIC;

    delete levelJSON.levelTopic;
    delete levelJSON.levelTopic?.topicSection;

    const responsePayload = {
      NAME_SECTION,
      NAME_TOPIC,
      ...levelJSON,
    };

    response(200, responsePayload, "Success", res);
  } catch (error) {
    console.log(error);
    response(500, null, "Internal Server Error", res);
  }
};

export const getLevelForAdmin = async (req, res) => {
  const { page = 1, limit = 10, search = "", sort = "time" } = req.query;

  try {
    const { count, rows: levels } = await models.Level.findAndCountAll({
      where: {
        IS_DELETED: 0,
        ...(search && {
          [models.Op.or]: [
            {
              "$levelTopic->topicSection.NAME_SECTION$": {
                [models.Op.like]: `%${search}%`,
              },
            },
            {
              "$levelTopic.NAME_TOPIC$": {
                [models.Op.like]: `%${search}%`,
              },
            },
            {
              NAME_LEVEL: { [models.Op.like]: `%${search}%` },
            },
          ],
        }),
      },
      attributes: ["ID_LEVEL", "NAME_LEVEL", "TIME_LEVEL"],
      include: [
        {
          model: models.Topic,
          as: "levelTopic",
          attributes: ["ID_TOPIC", "NAME_TOPIC"],
          include: [
            {
              model: models.Section,
              as: "topicSection",
              attributes: ["ID_SECTION", "NAME_SECTION"],
            },
          ],
        },
      ],
      distinct: true,
    });

    const formattedLevels = levels.map((level) => ({
      ID_LEVEL: level.ID_LEVEL,
      ID_SECTION: level.levelTopic.topicSection.ID_SECTION,
      ID_TOPIC: level.levelTopic.ID_TOPIC,
      NAME_SECTION: level.levelTopic.topicSection.NAME_SECTION,
      NAME_TOPIC: level.levelTopic.NAME_TOPIC,
      NAME_LEVEL: level.NAME_LEVEL,
      TIME_LEVEL: level.TIME_LEVEL,
    }));

    if (sort === "section") {
      formattedLevels.sort((a, b) =>
        a.NAME_SECTION.localeCompare(b.NAME_SECTION)
      );
    } else if (sort === "topic") {
      formattedLevels.sort((a, b) => {
        const topicComparison = a.NAME_TOPIC.localeCompare(b.NAME_TOPIC);
        if (topicComparison === 0) {
          if (a.NAME_LEVEL === "Pretest") return -1;
          if (b.NAME_LEVEL === "Pretest") return 1;

          const levelA = parseInt(a.NAME_LEVEL.replace("Level ", "")) || 0;
          const levelB = parseInt(b.NAME_LEVEL.replace("Level ", "")) || 0;
          return levelA - levelB;
        }
        return topicComparison;
      });
    } else if (sort === "level") {
      formattedLevels.sort((a, b) => {
        if (a.NAME_LEVEL === "Pretest") return -1;
        if (b.NAME_LEVEL === "Pretest") return 1;

        const levelA = parseInt(a.NAME_LEVEL.replace("Level ", "")) || 0;
        const levelB = parseInt(b.NAME_LEVEL.replace("Level ", "")) || 0;

        return levelA - levelB;
      });
    } else {
      formattedLevels.sort(
        (a, b) => new Date(b.TIME_LEVEL) - new Date(a.TIME_LEVEL)
      );
    }

    const paginatedLevels = formattedLevels.slice(
      (page - 1) * limit,
      page * limit
    );

    const totalPages = Math.ceil(count / limit);
    const currentPage = parseInt(page);

    response(
      200,
      {
        levels: paginatedLevels,
        currentPage,
        totalPages,
        totalItems: count,
      },
      "Levels retrieved successfully",
      res
    );
  } catch (error) {
    console.log(error);
    response(500, null, "Error retrieving levels data!", res);
  }
};

export const getLevelsByTopicId = async (req, res) => {
  try {
    const { idTopic } = req.params;
    const { ID } = req.user;

    const topicExists = await models.Topic.findByPk(idTopic, {
      include: {
        model: models.Section,
        as: "topicSection",
        attributes: ["NAME_SECTION"],
      },
    });

    if (!topicExists) {
      return res.status(404).json({ message: "Topic not found" });
    }

    const levels = await models.Level.findAll({
      where: {
        ID_TOPIC: idTopic,
        IS_DELETED: 0,
      },
      attributes: {
        exclude: [
          "ROUTE_1",
          "ROUTE_2",
          "ROUTE_3",
          "ROUTE_4",
          "ROUTE_5",
          "ROUTE_6",
        ],
      },
      include: [
        {
          model: models.StdLearning,
          as: "stdLearning",
          attributes: [
            "SCORE",
            "ID_STUDENT_LEARNING",
            "STUDENT_START",
            "STUDENT_FINISH",
            "NEXT_LEARNING",
          ],
          where: {
            ID: ID,
          },
          required: false,
          order: [["STUDENT_START", "DESC"]],
          limit: 1,
        },
        {
          model: models.Topic,
          as: "levelTopic",
          attributes: ["NAME_TOPIC"],
          include: {
            model: models.Section,
            as: "topicSection",
            attributes: ["NAME_SECTION"],
          },
        },
      ],
    });

    if (!levels || levels.length === 0) {
      return res
        .status(404)
        .json({ message: "No levels found for the given topic." });
    }

    const lastCompletedLearning = await models.StdLearning.findOne({
      where: {
        ID: ID,
        STUDENT_FINISH: { [models.Op.not]: null },
      },
      include: [
        {
          model: models.Level,
          as: "level",
          attributes: ["ID_LEVEL", "NAME_LEVEL"],
          where: {
            ID_TOPIC: idTopic,
            IS_DELETED: 0,
          },
        },
      ],
      order: [["STUDENT_FINISH", "DESC"]],
    });

    let currentLearningLevel = null;

    if (lastCompletedLearning?.NEXT_LEARNING) {
      currentLearningLevel = await models.Level.findOne({
        where: {
          ID_LEVEL: lastCompletedLearning.NEXT_LEARNING,
          IS_DELETED: 0,
        },
        attributes: ["ID_LEVEL", "NAME_LEVEL"],
      });
    }

    const nextLearningLevel = currentLearningLevel;

    const unlockedLevels = lastCompletedLearning
      ? await models.Level.findAll({
          where: {
            ID_TOPIC: idTopic,
            IS_DELETED: 0,
            [models.Op.or]: [
              { NAME_LEVEL: { [models.Op.lt]: nextLearningLevel?.NAME_LEVEL } },
              { NAME_LEVEL: "Pretest" },
            ],
          },
          attributes: ["NAME_LEVEL"],
          order: [["NAME_LEVEL", "ASC"]],
        })
      : [{ NAME_LEVEL: "Pretest" }];

    const unlockedLevelNames = unlockedLevels.map((lvl) => lvl.NAME_LEVEL);

    if (
      nextLearningLevel &&
      !unlockedLevelNames.includes(nextLearningLevel.NAME_LEVEL)
    ) {
      unlockedLevelNames.push(nextLearningLevel.NAME_LEVEL);
    }

    const levelsWithScore = levels.map((level) => {
      const SCORE =
        level.stdLearning && level.stdLearning.length > 0
          ? level.stdLearning[0]?.SCORE
          : null;
      const ID_STUDENT_LEARNING =
        level.stdLearning && level.stdLearning.length > 0
          ? level.stdLearning[0]?.ID_STUDENT_LEARNING
          : null;

      const levelJSON = level.toJSON();
      const NAME_SECTION = levelJSON.levelTopic.topicSection.NAME_SECTION;
      const NAME_TOPIC = levelJSON.levelTopic.NAME_TOPIC;

      delete levelJSON.stdLearning;
      delete levelJSON.levelTopic;
      delete levelJSON.levelTopic?.topicSection;

      const isUnlocked = unlockedLevelNames.includes(levelJSON.NAME_LEVEL);

      if (isUnlocked) {
        return {
          NAME_SECTION,
          NAME_TOPIC,
          ...levelJSON,
          ID_STUDENT_LEARNING,
          SCORE,
          IS_PRETEST: levelJSON.NAME_LEVEL === "Pretest" ? 1 : 0,
        };
      } else {
        return {
          ID_LEVEL: levelJSON.ID_LEVEL,
          NAME_LEVEL: levelJSON.NAME_LEVEL,
          IS_PRETEST: levelJSON.NAME_LEVEL === "Pretest" ? 1 : 0,
          SCORE,
        };
      }
    });

    const sortedLevels = levelsWithScore.sort((a, b) => {
      if (a.NAME_LEVEL === "Pretest") return -1;
      if (b.NAME_LEVEL === "Pretest") return 1;

      const levelA = parseInt(a.NAME_LEVEL.replace("Level ", ""));
      const levelB = parseInt(b.NAME_LEVEL.replace("Level ", ""));

      return levelA - levelB;
    });

    const responsePayload = {
      lastCompletedLevel: lastCompletedLearning
        ? {
            ID_STUDENT_LEARNING: lastCompletedLearning.ID_STUDENT_LEARNING,
            ID_LEVEL: lastCompletedLearning.level.ID_LEVEL,
            NAME_LEVEL: lastCompletedLearning.level.NAME_LEVEL,
            SCORE: lastCompletedLearning.SCORE,
            NEXT_LEARNING: lastCompletedLearning.NEXT_LEARNING,
            NEXT_LEARNING_LEVEL: nextLearningLevel
              ? nextLearningLevel.NAME_LEVEL
              : null,
            FINISHED_AT: lastCompletedLearning.STUDENT_FINISH,
            UNLOCKED_LEVELS: unlockedLevelNames,
          }
        : {
            UNLOCKED_LEVELS: unlockedLevelNames,
          },
      levels: sortedLevels,
    };

    res.status(200).json({ message: "Success", data: responsePayload });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Internal Server Error" });
  }
};

export const createLevel = async (req, res, next) => {
  const { NAME_LEVEL, ID_SECTION, ID_TOPIC, CONTENT, VIDEO } = req.body;
  const { AUDIO, IMAGE } = req.filesToSave || {};

  if (!NAME_LEVEL) {
    clearFileBuffers({ AUDIO, IMAGE });
    return response(400, null, "Level name is required", res);
  }

  if (!ID_SECTION) {
    clearFileBuffers({ AUDIO, IMAGE });
    return response(400, null, "Section is required", res);
  }

  if (!ID_TOPIC) {
    clearFileBuffers({ AUDIO, IMAGE });
    return response(400, null, "Topic is required", res);
  }

  const transaction = await models.db.transaction();

  try {
    const sectionWithTopic = await models.Topic.findOne({
      where: { ID_SECTION, ID_TOPIC },
      transaction,
    });

    if (!sectionWithTopic) {
      clearFileBuffers({ AUDIO, IMAGE });
      await transaction.rollback();
      return response(
        400,
        null,
        "Topic does not relate to the provided Section!",
        res
      );
    }

    const existingLevel = await models.Level.findOne({
      where: {
        NAME_LEVEL,
        ID_TOPIC,
        IS_DELETED: 0,
      },
      transaction,
    });

    if (existingLevel) {
      clearFileBuffers({ AUDIO, IMAGE });
      await transaction.rollback();
      return response(
        409,
        null,
        "A level with this name already exists under this topic",
        res
      );
    }

    const newLevel = await models.Level.create(
      {
        NAME_LEVEL,
        ID_SECTION,
        ID_TOPIC,
        IS_PRETEST: req.body.IS_PRETEST || 0,
        CONTENT,
        VIDEO: VIDEO || null,
        AUDIO: null,
        IMAGE: null,
        ROUTE_1: req.body.ROUTE_1,
        ROUTE_2: req.body.ROUTE_2,
        ROUTE_3: req.body.ROUTE_3,
        ROUTE_4: req.body.ROUTE_4,
        ROUTE_5: req.body.ROUTE_5,
        ROUTE_6: req.body.ROUTE_6,
      },
      { transaction }
    );

    req.body.newLevelId = newLevel.ID_LEVEL;

    const audioFilename = AUDIO
      ? saveFileToDisk(AUDIO, "AUDIO", ID_TOPIC, ID_SECTION, newLevel.ID_LEVEL)
      : null;
    const imageFilename = IMAGE
      ? saveFileToDisk(IMAGE, "IMAGE", ID_TOPIC, ID_SECTION, newLevel.ID_LEVEL)
      : null;

    newLevel.AUDIO = audioFilename;
    newLevel.IMAGE = imageFilename;
    await newLevel.save({ transaction });

    await transaction.commit();

    await updateOtherLevelsRoutes(req, res, next);

    response(201, newLevel, "Level created successfully", res);
  } catch (error) {
    console.log(error);
    clearFileBuffers({ AUDIO, IMAGE });
    await transaction.rollback();
    return response(500, null, "Internal Server Error", res);
  }
};

export const updateLevelById = async (req, res, next) => {
  const { id } = req.params;
  const { NAME_LEVEL, ID_SECTION, ID_TOPIC, CONTENT, VIDEO } = req.body;

  const { AUDIO, IMAGE } = req.filesToSave || {};

  const transaction = await models.db.transaction();

  try {
    const level = await models.Level.findByPk(id, { transaction });

    if (!level) {
      clearFileBuffers({ AUDIO, IMAGE });
      await transaction.rollback();
      return response(404, null, "Level not found", res);
    }

    const sectionWithTopic = await models.Topic.findOne({
      where: { ID_SECTION, ID_TOPIC },
      transaction,
    });

    if (!sectionWithTopic) {
      clearFileBuffers({ AUDIO, IMAGE });
      await transaction.rollback();
      return response(
        400,
        null,
        "Topic does not relate to the provided Section",
        res
      );
    }

    if (NAME_LEVEL && ID_TOPIC) {
      const existingLevel = await models.Level.findOne({
        where: {
          NAME_LEVEL,
          ID_TOPIC,
          ID_LEVEL: { [models.Sequelize.Op.ne]: id },
          IS_DELETED: 0,
        },
        transaction,
      });

      if (existingLevel) {
        clearFileBuffers({ AUDIO, IMAGE });
        await transaction.rollback();
        return response(
          409,
          null,
          "A level with this name already exists under this topic",
          res
        );
      }
    }

    if (NAME_LEVEL) {
      level.NAME_LEVEL = NAME_LEVEL;
      level.IS_PRETEST = NAME_LEVEL === "Pretest" ? 1 : 0;
    }
    if (ID_SECTION) level.ID_SECTION = ID_SECTION;
    if (ID_TOPIC) level.ID_TOPIC = ID_TOPIC;
    if (CONTENT) level.CONTENT = CONTENT;
    if (VIDEO) level.VIDEO = VIDEO;

    if (AUDIO) {
      if (level.AUDIO) {
        const oldAudioPath = path.join(
          "public/uploads/level/audio",
          level.AUDIO
        );
        if (fs.existsSync(oldAudioPath)) fs.unlinkSync(oldAudioPath);
      }
      level.AUDIO = saveFileToDisk(
        AUDIO,
        "AUDIO",
        ID_TOPIC || level.ID_TOPIC,
        ID_SECTION || level.ID_SECTION,
        level.ID_LEVEL
      );
    }

    if (IMAGE) {
      if (level.IMAGE) {
        const oldImagePath = path.join(
          "public/uploads/level/image",
          level.IMAGE
        );
        if (fs.existsSync(oldImagePath)) fs.unlinkSync(oldImagePath);
      }
      level.IMAGE = saveFileToDisk(
        IMAGE,
        "IMAGE",
        ID_TOPIC || level.ID_TOPIC,
        ID_SECTION || level.ID_SECTION,
        level.ID_LEVEL
      );
    }

    await level.save({ transaction });

    await transaction.commit();

    await updateOtherLevelsRoutes(req, res, next);

    response(200, level, "Level updated successfully", res);
  } catch (error) {
    console.log(error);
    clearFileBuffers({ AUDIO, IMAGE });
    await transaction.rollback();
    return response(500, null, "Internal Server Error", res);
  }
};

export const deleteLevelById = async (req, res, next) => {
  const { id } = req.params;

  try {
    const level = await models.Level.findByPk(id);

    if (!level) {
      return response(404, null, "Level not found", res);
    }

    level.IS_DELETED = 1;
    await level.save();

    await models.Exercise.update(
      { IS_DELETED: 1 },
      { where: { ID_LEVEL: id } }
    );

    req.body.newLevelId = level.ID_LEVEL;

    await updateOtherLevelsRoutesOnDelete(req, res, next);

    response(
      200,
      null,
      "Level and related exercises soft deleted successfully",
      res
    );
  } catch (error) {
    console.log(error);
    return response(500, null, "Internal Server Error", res);
  }
};

export const deleteLevelFileById = async (req, res) => {
  const { id } = req.params;
  const { fileType } = req.body;

  if (!["audio", "image", "video"].includes(fileType)) {
    return response(400, null, "Invalid file type specified", res);
  }

  try {
    const level = await models.Level.findByPk(id);

    if (!level) {
      return response(404, null, "Level not found", res);
    }

    let filePath;
    let fileName;

    if (fileType === "audio" && level.AUDIO) {
      fileName = level.AUDIO;
      filePath = path.join("public/uploads/level/audio", fileName);
      level.AUDIO = null;
    } else if (fileType === "image" && level.IMAGE) {
      fileName = level.IMAGE;
      filePath = path.join("public/uploads/level/image", fileName);
      level.IMAGE = null;
    } else if (fileType === "video" && level.VIDEO) {
      level.VIDEO = null;
    } else {
      return response(
        404,
        null,
        `${
          fileType.charAt(0).toUpperCase() + fileType.slice(1)
        } file not found`,
        res
      );
    }

    if (filePath && fs.existsSync(filePath)) {
      fs.unlinkSync(filePath);
    }

    await level.save();

    response(
      200,
      level,
      `${
        fileType.charAt(0).toUpperCase() + fileType.slice(1)
      } file deleted successfully`,
      res
    );
  } catch (error) {
    console.log(error);
    response(500, null, "Internal Server Error", res);
  }
};

export const deleteLevelFilesById = async (req, res) => {
  const { id } = req.params;
  const { fileName } = req.body;

  const filePattern =
    /^(AUDIO|IMAGE)-([a-f0-9-]{36})-[a-f0-9]{32}\.(mp3|jpg|jpeg|png)$/;
  const match = fileName.match(filePattern);

  if (!match) {
    return response(400, null, "Invalid file name format", res);
  }

  const fileType = match[1];
  const levelIdFromFile = match[2];

  if (levelIdFromFile !== id) {
    return response(400, null, "Level ID in file name does not match", res);
  }

  try {
    const level = await models.Level.findByPk(id);

    if (!level) {
      return response(404, null, "Level not found", res);
    }

    let filePath;

    if (fileType === "AUDIO") {
      filePath = path.join("public/uploads/level/audio", fileName);
    } else if (fileType === "IMAGE") {
      filePath = path.join("public/uploads/level/image", fileName);
    } else {
      return response(400, null, "Invalid file type", res);
    }

    if (filePath && fs.existsSync(filePath)) {
      fs.unlinkSync(filePath);
      return response(200, null, `${fileType} file deleted successfully`, res);
    } else {
      return response(404, null, "File not found on the server", res);
    }
  } catch (error) {
    console.log(error);
    response(500, null, "Internal Server Error", res);
  }
};

export const getPreviousLevel = async (req, res) => {
  try {
    const { next_learning } = req.params;
    const { ID } = req.user;

    const currentLevel = await models.Level.findByPk(next_learning, {
      where: {
        IS_DELETED: 0,
      },
      include: [
        {
          model: models.StdLearning,
          as: "stdLearning",
          attributes: [
            "SCORE",
            "ID_STUDENT_LEARNING",
            "STUDENT_START",
            "STUDENT_FINISH",
          ],
          where: {
            ID: ID,
          },
          required: false,
          order: [["STUDENT_FINISH", "DESC"]],
          limit: 1,
        },
      ],
      attributes: {
        exclude: [
          "ROUTE_1",
          "ROUTE_2",
          "ROUTE_3",
          "ROUTE_4",
          "ROUTE_5",
          "ROUTE_6",
        ],
      },
    });

    if (!currentLevel) {
      return res.status(404).json({ message: "Level not found" });
    }

    const { NAME_LEVEL, ID_TOPIC } = currentLevel;
    const levelNumber = parseInt(NAME_LEVEL.replace("Level ", ""));

    if (isNaN(levelNumber)) {
      return res.status(400).json({ message: "Invalid level format" });
    }

    const previousLevels = await models.Level.findAll({
      where: {
        ID_TOPIC: ID_TOPIC,
        IS_DELETED: 0,
        NAME_LEVEL: {
          [models.Op.or]: [
            { [models.Op.like]: "Pretest" },
            { [models.Op.regexp]: `^Level [0-9]+$` },
          ],
        },
        [models.Op.or]: [
          { IS_PRETEST: 1 },
          {
            NAME_LEVEL: {
              [models.Op.lt]: `Level ${levelNumber}`,
            },
          },
        ],
      },
      attributes: {
        exclude: [
          "ROUTE_1",
          "ROUTE_2",
          "ROUTE_3",
          "ROUTE_4",
          "ROUTE_5",
          "ROUTE_6",
        ],
      },
      include: [
        {
          model: models.StdLearning,
          as: "stdLearning",
          attributes: [
            "SCORE",
            "ID_STUDENT_LEARNING",
            "STUDENT_START",
            "STUDENT_FINISH",
          ],
          where: {
            ID: ID,
          },
          required: false,
          order: [["STUDENT_START", "DESC"]],
          limit: 1,
        },
      ],
    });

    const previousLevelsWithScore = previousLevels.map((level) => {
      const SCORE =
        level.stdLearning && level.stdLearning.length > 0
          ? level.stdLearning[0]?.SCORE
          : null;
      const ID_STUDENT_LEARNING =
        level.stdLearning && level.stdLearning.length > 0
          ? level.stdLearning[0]?.ID_STUDENT_LEARNING
          : null;

      const levelJSON = level.toJSON();
      delete levelJSON.stdLearning;

      return {
        ...levelJSON,
        ID_STUDENT_LEARNING,
        SCORE,
      };
    });

    const currentLevelWithScore = {
      ...currentLevel.toJSON(),
      ID_STUDENT_LEARNING:
        currentLevel.stdLearning && currentLevel.stdLearning.length > 0
          ? currentLevel.stdLearning[0]?.ID_STUDENT_LEARNING
          : null,
      SCORE:
        currentLevel.stdLearning && currentLevel.stdLearning.length > 0
          ? currentLevel.stdLearning[0]?.SCORE
          : null,
    };

    delete currentLevelWithScore.stdLearning;

    const sortedLevels = previousLevelsWithScore.sort((a, b) => {
      if (a.NAME_LEVEL === "Pretest") return -1;
      if (b.NAME_LEVEL === "Pretest") return 1;

      const levelA = parseInt(a.NAME_LEVEL.replace("Level ", ""));
      const levelB = parseInt(b.NAME_LEVEL.replace("Level ", ""));

      return levelA - levelB;
    });

    if (!sortedLevels.length && !currentLevelWithScore) {
      return res.status(404).json({ message: "No levels found" });
    }

    const result = {
      currentLevel: currentLevelWithScore,
      previousLevels: sortedLevels,
    };

    res.status(200).json({ message: "Success", data: result });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Internal Server Error" });
  }
};

export const uploadLevelFile = async (req, res) => {
  const { levelId } = req.params;

  try {
    const level = await models.Level.findByPk(levelId);

    if (!level) {
      return response(404, null, "Level not found", res);
    }

    const filesToSave = req.filesToSave;

    if (!filesToSave || Object.keys(filesToSave).length === 0) {
      return response(400, null, "No files to upload", res);
    }

    const { ID_TOPIC, ID_SECTION } = level;
    const savedFiles = {};

    Object.keys(filesToSave).forEach((key) => {
      let filename;
      if (key.startsWith("AUDIO")) {
        const audioFile = filesToSave[key];
        filename = saveFileToDisk(
          audioFile,
          "AUDIO",
          ID_TOPIC,
          ID_SECTION,
          levelId
        );
      } else if (key.startsWith("IMAGE")) {
        const imageFile = filesToSave[key];
        filename = saveFileToDisk(
          imageFile,
          "IMAGE",
          ID_TOPIC,
          ID_SECTION,
          levelId
        );
      }

      if (filename) {
        savedFiles[key] = filename;
      }
    });

    if (Object.keys(savedFiles).length === 0) {
      return response(400, null, "Failed to save files", res);
    }

    return response(200, savedFiles, "Files uploaded successfully", res);
  } catch (error) {
    console.error(error);
    return response(500, null, "Internal server error", res);
  }
};

export const getLevelFiles = async (req, res) => {
  const { levelId } = req.params;

  try {
    const audioFolderPath = path.join("public/uploads/level/audio");
    const imageFolderPath = path.join("public/uploads/level/image");

    const getFilesByLevelId = (folderPath, fileType) => {
      if (fs.existsSync(folderPath)) {
        const files = fs.readdirSync(folderPath);
        return files.filter((file) =>
          file.startsWith(`${fileType}-${levelId}`)
        );
      }
      return [];
    };

    const audioFiles = getFilesByLevelId(audioFolderPath, "AUDIO");
    const imageFiles = getFilesByLevelId(imageFolderPath, "IMAGE");

    if (audioFiles.length === 0 && imageFiles.length === 0) {
      return response(404, null, "No files found for this level", res);
    }

    const levelFiles = {
      audioFiles,
      imageFiles,
    };

    return response(200, levelFiles, "Files retrieved successfully", res);
  } catch (error) {
    console.error(error);
    return response(500, null, "Internal server error", res);
  }
};
