import models from "../../models/index.js";
import response from "../../response.js";

export const checkLevelsPerTopic = async (req, res, next) => {
  const { ID_TOPIC } = req.body;

  try {
    const levelCount = await models.Level.count({
      where: {
        ID_TOPIC,
        IS_DELETED: 0,
      },
    });

    if (levelCount >= 7) {
      return response(
        400,
        null,
        "Cannot add more than 6 levels to a single topic",
        res
      );
    }

    next();
  } catch (error) {
    console.log(error);
    return response(500, null, "Internal Server Error", res);
  }
};

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

  try {
    const level = await models.Level.findByPk(id, {
      attributes: ["ID_SECTION", "ID_TOPIC"],
    });

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

    req.body.ID_SECTION = level.ID_SECTION;
    req.body.ID_TOPIC = level.ID_TOPIC;

    next();
  } catch (error) {
    console.log(error);
    return response(500, null, "Internal Server Error", res);
  }
};

export const autoCalculateRoutes = async (req, res, next) => {
  const { NAME_LEVEL, ID_TOPIC } = req.body;

  try {
    let routes = {
      ROUTE_1: 0,
      ROUTE_2: 0,
      ROUTE_3: 0,
      ROUTE_4: 0,
      ROUTE_5: 0,
      ROUTE_6: 0,
    };

    const levelTitles = [
      "Pretest",
      "Level 1",
      "Level 2",
      "Level 3",
      "Level 4",
      "Level 5",
      "Level 6",
    ];

    const levels = await models.Level.findAll({
      where: {
        ID_TOPIC,
        NAME_LEVEL: {
          [models.Sequelize.Op.in]: levelTitles,
        },
        IS_DELETED: 0,
      },
    });

    levels.sort(
      (a, b) =>
        levelTitles.indexOf(a.NAME_LEVEL) - levelTitles.indexOf(b.NAME_LEVEL)
    );

    const levelMap = {};
    levels.forEach((level) => {
      levelMap[level.NAME_LEVEL] = level.ID_LEVEL;
    });

    switch (NAME_LEVEL) {
      case "Pretest":
        req.body.IS_PRETEST = 1;
        routes.ROUTE_1 = levelMap["Level 1"] || 0;
        routes.ROUTE_2 = levelMap["Level 2"] || 0;
        routes.ROUTE_3 = levelMap["Level 3"] || 0;
        routes.ROUTE_4 = levelMap["Level 4"] || 0;
        routes.ROUTE_5 = levelMap["Level 5"] || 0;
        routes.ROUTE_6 = levelMap["Level 6"] || 0;
        break;
      case "Level 1":
        routes.ROUTE_1 = levelMap["Pretest"] || 0;
        routes.ROUTE_2 = levelMap["Level 2"] || 0;
        routes.ROUTE_3 = levelMap["Level 3"] || 0;
        routes.ROUTE_4 = levelMap["Level 4"] || 0;
        routes.ROUTE_5 = levelMap["Level 5"] || 0;
        routes.ROUTE_6 = levelMap["Level 6"] || 0;
        break;
      case "Level 2":
        routes.ROUTE_1 = levelMap["Pretest"] || 0;
        routes.ROUTE_2 = levelMap["Level 1"] || 0;
        routes.ROUTE_3 = levelMap["Level 3"] || 0;
        routes.ROUTE_4 = levelMap["Level 4"] || 0;
        routes.ROUTE_5 = levelMap["Level 5"] || 0;
        routes.ROUTE_6 = levelMap["Level 6"] || 0;
        break;
      case "Level 3":
        routes.ROUTE_1 = levelMap["Pretest"] || 0;
        routes.ROUTE_2 = levelMap["Level 1"] || 0;
        routes.ROUTE_3 = levelMap["Level 2"] || 0;
        routes.ROUTE_4 = levelMap["Level 4"] || 0;
        routes.ROUTE_5 = levelMap["Level 5"] || 0;
        routes.ROUTE_6 = levelMap["Level 6"] || 0;
        break;
      case "Level 4":
        routes.ROUTE_1 = levelMap["Pretest"] || 0;
        routes.ROUTE_2 = levelMap["Level 1"] || 0;
        routes.ROUTE_3 = levelMap["Level 2"] || 0;
        routes.ROUTE_4 = levelMap["Level 3"] || 0;
        routes.ROUTE_5 = levelMap["Level 5"] || 0;
        routes.ROUTE_6 = levelMap["Level 6"] || 0;
        break;
      case "Level 5":
        routes.ROUTE_1 = levelMap["Pretest"] || 0;
        routes.ROUTE_2 = levelMap["Level 1"] || 0;
        routes.ROUTE_3 = levelMap["Level 2"] || 0;
        routes.ROUTE_4 = levelMap["Level 3"] || 0;
        routes.ROUTE_5 = levelMap["Level 4"] || 0;
        routes.ROUTE_6 = levelMap["Level 6"] || 0;
        break;
      case "Level 6":
        routes.ROUTE_1 = levelMap["Pretest"] || 0;
        routes.ROUTE_2 = levelMap["Level 1"] || 0;
        routes.ROUTE_3 = levelMap["Level 2"] || 0;
        routes.ROUTE_4 = levelMap["Level 3"] || 0;
        routes.ROUTE_5 = levelMap["Level 4"] || 0;
        routes.ROUTE_6 = levelMap["Level 5"] || 0;
        break;
    }

    req.body.ROUTE_1 = routes.ROUTE_1;
    req.body.ROUTE_2 = routes.ROUTE_2;
    req.body.ROUTE_3 = routes.ROUTE_3;
    req.body.ROUTE_4 = routes.ROUTE_4;
    req.body.ROUTE_5 = routes.ROUTE_5;
    req.body.ROUTE_6 = routes.ROUTE_6;

    next();
  } catch (error) {
    console.log(error);
    return response(500, null, "Internal Server Error", res);
  }
};

export const updateOtherLevelsRoutes = async (req, res, next) => {
  const { NAME_LEVEL, ID_TOPIC, newLevelId } = req.body;

  try {
    const levelTitles = [
      "Pretest",
      "Level 1",
      "Level 2",
      "Level 3",
      "Level 4",
      "Level 5",
      "Level 6",
    ];
    const currentLevelIndex = levelTitles.indexOf(NAME_LEVEL);

    if (currentLevelIndex !== -1) {
      const levels = await models.Level.findAll({
        where: {
          ID_TOPIC,
          NAME_LEVEL: {
            [models.Sequelize.Op.in]: levelTitles,
          },
          IS_DELETED: 0,
        },
      });

      levels.sort(
        (a, b) =>
          levelTitles.indexOf(a.NAME_LEVEL) - levelTitles.indexOf(b.NAME_LEVEL)
      );

      const levelMap = {};
      levels.forEach((level) => {
        levelMap[level.NAME_LEVEL] = level.ID_LEVEL;
      });

      if (newLevelId) {
        levelMap[NAME_LEVEL] = newLevelId;
      }

      for (let i = 0; i < levelTitles.length; i++) {
        if (i === currentLevelIndex) continue;

        const levelTitle = levelTitles[i];
        const updateData = {};

        if (i === 0) {
          updateData.ROUTE_1 = levelMap["Level 1"] || 0;
          updateData.ROUTE_2 = levelMap["Level 2"] || 0;
          updateData.ROUTE_3 = levelMap["Level 3"] || 0;
          updateData.ROUTE_4 = levelMap["Level 4"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 1) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 2"] || 0;
          updateData.ROUTE_3 = levelMap["Level 3"] || 0;
          updateData.ROUTE_4 = levelMap["Level 4"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 2) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 3"] || 0;
          updateData.ROUTE_4 = levelMap["Level 4"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 3) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 2"] || 0;
          updateData.ROUTE_4 = levelMap["Level 4"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 4) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 2"] || 0;
          updateData.ROUTE_4 = levelMap["Level 3"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 5) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 2"] || 0;
          updateData.ROUTE_4 = levelMap["Level 3"] || 0;
          updateData.ROUTE_5 = levelMap["Level 4"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 6) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 2"] || 0;
          updateData.ROUTE_4 = levelMap["Level 3"] || 0;
          updateData.ROUTE_5 = levelMap["Level 4"] || 0;
          updateData.ROUTE_6 = levelMap["Level 5"] || 0;
        }

        await models.Level.update(updateData, {
          where: {
            ID_TOPIC,
            NAME_LEVEL: levelTitle,
          },
        });
      }
    }

    next();
  } catch (error) {
    console.log(error);
    return response(500, null, "Internal Server Error", res);
  }
};

export const autoGenerateLevelUpdateOtherRoutes = async (req, res, createdLevels) => {
  const { NAME_LEVEL, ID_TOPIC, newLevelId } = req.body;

  try {
    const levelTitles = [
      "Pretest",
      "Level 1",
      "Level 2",
      "Level 3",
      "Level 4",
      "Level 5",
      "Level 6",
    ];
    const currentLevelIndex = levelTitles.indexOf(NAME_LEVEL);

    if (currentLevelIndex !== -1) {
      const levels = await models.Level.findAll({
        where: {
          ID_TOPIC,
          NAME_LEVEL: {
            [models.Sequelize.Op.in]: levelTitles,
          },
          IS_DELETED: 0,
        },
      });

      levels.sort(
        (a, b) =>
          levelTitles.indexOf(a.NAME_LEVEL) - levelTitles.indexOf(b.NAME_LEVEL)
      );

      const levelMap = {};
      levels.forEach((level) => {
        levelMap[level.NAME_LEVEL] = level.ID_LEVEL;
      });

      if (newLevelId) {
        levelMap[NAME_LEVEL] = newLevelId;
      }

      for (let i = 0; i < levelTitles.length; i++) {
        if (i === currentLevelIndex) continue;

        const levelTitle = levelTitles[i];
        const updateData = {};

        if (i === 0) {
          updateData.ROUTE_1 = levelMap["Level 1"] || 0;
          updateData.ROUTE_2 = levelMap["Level 2"] || 0;
          updateData.ROUTE_3 = levelMap["Level 3"] || 0;
          updateData.ROUTE_4 = levelMap["Level 4"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 1) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 2"] || 0;
          updateData.ROUTE_3 = levelMap["Level 3"] || 0;
          updateData.ROUTE_4 = levelMap["Level 4"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 2) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 3"] || 0;
          updateData.ROUTE_4 = levelMap["Level 4"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 3) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 2"] || 0;
          updateData.ROUTE_4 = levelMap["Level 4"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 4) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 2"] || 0;
          updateData.ROUTE_4 = levelMap["Level 3"] || 0;
          updateData.ROUTE_5 = levelMap["Level 5"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 5) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 2"] || 0;
          updateData.ROUTE_4 = levelMap["Level 3"] || 0;
          updateData.ROUTE_5 = levelMap["Level 4"] || 0;
          updateData.ROUTE_6 = levelMap["Level 6"] || 0;
        } else if (i === 6) {
          updateData.ROUTE_1 = levelMap["Pretest"] || 0;
          updateData.ROUTE_2 = levelMap["Level 1"] || 0;
          updateData.ROUTE_3 = levelMap["Level 2"] || 0;
          updateData.ROUTE_4 = levelMap["Level 3"] || 0;
          updateData.ROUTE_5 = levelMap["Level 4"] || 0;
          updateData.ROUTE_6 = levelMap["Level 5"] || 0;
        }

        await models.Level.update(updateData, {
          where: {
            ID_TOPIC,
            NAME_LEVEL: levelTitle,
          },
        });
      }
    }
  } catch (error) {
    console.log(error);
    return response(500, null, "Internal Server Error", res);
  }
};

export const updateOtherLevelsRoutesOnDelete = async (req, res, next) => {
  const { newLevelId } = req.body;

  try {
    if (!newLevelId) {
      return response(400, null, "No level provided for deletion!", res);
    }

    const levelsToUpdate = await models.Level.findAll({
      where: {
        IS_DELETED: 0,
        [models.Sequelize.Op.or]: [
          { ROUTE_1: newLevelId },
          { ROUTE_2: newLevelId },
          { ROUTE_3: newLevelId },
          { ROUTE_4: newLevelId },
          { ROUTE_5: newLevelId },
          { ROUTE_6: newLevelId },
        ],
      },
    });

    for (const level of levelsToUpdate) {
      const updateData = {};
      if (level.ROUTE_1 === newLevelId) updateData.ROUTE_1 = 0;
      if (level.ROUTE_2 === newLevelId) updateData.ROUTE_2 = 0;
      if (level.ROUTE_3 === newLevelId) updateData.ROUTE_3 = 0;
      if (level.ROUTE_4 === newLevelId) updateData.ROUTE_4 = 0;
      if (level.ROUTE_5 === newLevelId) updateData.ROUTE_5 = 0;
      if (level.ROUTE_6 === newLevelId) updateData.ROUTE_6 = 0;

      await level.update(updateData);
    }

    next();
  } catch (error) {
    console.log(error);
    return response(500, null, "Internal Server Error", res);
  }
};
