const { Op } = require("sequelize");
const dbSAPPS = require("../../helpers/db");
require("dotenv").config();

module.exports = {
  getAll,
  filter,
  option,
  count,
  create,
  update,
  enabled,
  delete: _delete,
};

async function getAll() {
  try {
    // Mengambil semua pengguna dan mengurutkannya berdasarkan kolom 'modified' secara menurun
    const majors = await dbSAPPS.Major.findAll({
      order: [["modified", "DESC"]],
      include: [
        {
          model: dbSAPPS.Faculty,
          as: "faculty",
          attributes: ["id", "display_name", "name"],
        },
      ],
    });

    // Mengembalikan respons dengan status 200 OK
    return {
      majors,
      success: true,
      message: "majors loaded successfully!",
    };
  } catch (error) {
    // Menangani error dan mengembalikan respons dengan status 500 Internal Server Error
    const errorMessage = error.message || "Failed to load majors!";
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function filter(params) {
  try {
    const filterConditions = {};

    // column-level filters
    if (params.f_display_name) {
      filterConditions.display_name = {
        [Op.like]: `%${params.f_display_name}%`,
      };
    }

    if (params.f_name) {
      filterConditions.name = {
        [Op.like]: `%${params.f_name}%`,
      };
    }

    if (params.f_faculty_display_name) {
      filterConditions["$faculty.display_name$"] = {
        [Op.like]: `%${params.f_faculty_display_name}%`,
      };
    }

    if (params.faculty_id) {
      filterConditions.faculty_id = params.faculty_id;
    }

    if (params.enabled) {
      filterConditions.enabled = params.enabled === "1" || params.enabled === true;
    }

    // global search q
    const andConditions = [];
    if (params.q) {
      andConditions.push({
        [Op.or]: [
          { display_name: { [Op.like]: `%${params.q}%` } },
          { name: { [Op.like]: `%${params.q}%` } },
          { "$faculty.display_name$": { [Op.like]: `%${params.q}%` } },
        ],
      });
    }

    const whereClause = {
      ...filterConditions,
      ...(andConditions.length ? { [Op.and]: andConditions } : {}),
    };

    // pagination logic
    const rawSize = parseInt(params?.pageSize, 10);
    const pageSize = Number.isFinite(rawSize) && rawSize > 0 ? Math.min(rawSize, 5000) : 100;
    const rawIndex = parseInt(params?.pageIndex, 10);
    const pageIndex = Number.isFinite(rawIndex) && rawIndex >= 0 ? rawIndex : 0;

    const { rows, count } = await dbSAPPS.Major.findAndCountAll({
      where: whereClause,
      order: [["modified", "DESC"]],
      offset: pageIndex * pageSize,
      limit: pageSize,
      subQuery: false,
      distinct: true,
      include: [
        {
          model: dbSAPPS.Faculty,
          as: "faculty",
          attributes: ["id", "display_name", "name"],
        },
      ],
    });

    return {
      success: true,
      majors: rows,
      totalCount: count,
      pageIndex,
      pageSize,
      message: "majors loaded successfully!",
    };
  } catch (error) {
    console.error("Error retrieving majors: ", error);
    return {
      success: false,
      message: error.message || "Failed to retrieve majors.",
    };
  }
}

async function option() {
  try {
    // Mencari pengguna yang diaktifkan dengan atribut tertentu
    const majors = await dbSAPPS.Major.findAll({
      attributes: ["id", "display_name", "name"],
      where: { enabled: true },
      order: [["display_name", "ASC"]], // Opsional: Mengurutkan hasil berdasarkan
    });

    // Mengembalikan hasil pencarian
    return {
      success: true,
      majors,
      message: "majors loaded successfully!",
    };
  } catch (error) {
    // Logging error untuk keperluan debugging
    console.error("Error retrieving majors: ", error);
    const errorMessage =
      error.message || "Failed to retrieve majors. Please try again later.";
    // Mengembalikan respons dengan status 500 Internal Server Error
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function count() {
  try {
    // Menghitung jumlah pengguna yang diaktifkan
    const count = await dbSAPPS.Major.count({
      where: { enabled: true },
    });

    // Mengembalikan hasil hitung
    return {
      success: true,
      count,
      message: "majors loaded successfully!",
    };
  } catch (error) {
    // Menangani error dan mengembalikan respons dengan status 500 Internal Server Error
    console.error("Error counting majors: ", error);
    return {
      success: false,
      message: "Failed to retrieve majors count. Please try again later.",
    };
  }
}

async function create(params) {
  try {
    // Validasi input
    if (!params.display_name || !params.name)
      return {
        success: false,
        message: "Major display name and major name are required!",
      };

    // Periksa apakah email sudah digunakan
    const existingNameNNumber = await dbSAPPS.Major.findOne({
      where: {
        display_name: params.display_name,
        name: params.name,
      },
    });
    if (existingNameNNumber)
      return {
        success: false,
        message: `Major name "${params.display_name}" and name "${params.name}" is already taken.`,
      };

    if (!params.enabled) params.enabled = true;
    const newMajor = await dbSAPPS.Major.create(params);

    // Respons sukses
    return {
      success: true,
      message: "Data major has been successfully adeded!",
      major: newMajor,
    };
  } catch (error) {
    // Menangani error dan mengembalikan respons dengan status 500 Internal Server Error
    const errorMessage =
      error.message || "An error occurred during major creation.";
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function update(id, params) {
  try {
    // Ambil dari database
    const major = await dbSAPPS.Major.findByPk(id);
    if (!major)
      return {
        success: false,
        message: "Major not found!",
      };

    // Validasi perubahan
    if (params.display_name && params.display_name !== major.display_name) {
      const existingMajorName = await dbSAPPS.Major.findOne({
        where: { display_name: params.display_name },
      });
      if (existingMajorName) {
        return {
          success: false,
          message: `Major name "${params.display_name}" is already taken. Try again!`,
        };
      }
    }

    if (params.name && params.name !== major.name) {
      const existingCityName = await dbSAPPS.Major.findOne({
        where: { name: params.name },
      });
      if (existingCityName) {
        return {
          success: false,
          message: `Major name "${params.name}" is already taken. Try again!`,
        };
      }
    }

    // Perbarui data kota
    await major.update(params);

    // Respons sukses
    return {
      success: true,
      message: "Your data major has been saved!",
    };
  } catch (error) {
    const errorMessage = error.message || "Failed to update major data.";
    // Menangani error dan mengembalikan respons dengan status 500 Internal Server Error
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function enabled(id, params) {
  try {
    const major = await dbSAPPS.Major.findByPk(id);
    if (!major)
      return {
        success: false,
        message: "Major not found!",
      };

    const updateData = {};
    updateData.enabled = params.enabled;
    if (params.modified_by) updateData.modified_by = params.modified_by;
    if (params.modified) updateData.modified = params.modified;

    // debug
    // console.log('id', id);
    // console.log('params', params);
    // console.log('updateData', updateData)

    await major.update(updateData);

    return {
      success: true,
      message: "Major has been updated!",
    };
  } catch (error) {
    const errorMessage = error.message || "Failed to update Major.";
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function _delete(id) {
  try {
    // Mengambil pengguna dari database
    const major = await dbSAPPS.Major.findByPk(id);
    if (!major) return { success: false, message: "major not found!" };

    // Menghapus pengguna dari database
    await major.destroy();

    // Respons sukses
    return {
      success: true,
      message: "major successfully deleted!",
    };
  } catch (error) {
    const errorMessage = error.message || "Failed to delete major.";
    // Menangani error dan mengembalikan respons dengan status 500 Internal Server Error
    return {
      success: false,
      message: errorMessage,
    };
  }
}
