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 {
    const periods = await dbSAPPS.Period.findAll({
      order: [["modified", "DESC"]],
      include: [
        {
          model: dbSAPPS.Year,
          as: "year",
          attributes: ["id", "display_name"],
        },
      ]
    });

    return {
      periods,
      success: true,
      message: "periods loaded successfully!",
    };
  } catch (error) {
    const errorMessage = error.message || "Failed to load periods!";
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function filter(params) {
  const filterConditions = {};
  
  // Handle 'f_' prefix from frontend table filters
  const cleanParams = { ...params };
  Object.keys(cleanParams).forEach((key) => {
    if (key.startsWith("f_")) {
      cleanParams[key.substring(2)] = cleanParams[key];
    }
  });

  if (cleanParams.q) {
    filterConditions[Op.or] = [
      { display_name: { [Op.like]: `%${cleanParams.q}%` } },
    ];
  }

  if (cleanParams.year_id) {
    // If it's a comma separated list (from multi-select), use Op.in
    if (String(cleanParams.year_id).includes(',')) {
        filterConditions.year_id = { [Op.in]: cleanParams.year_id.split(',') };
    } else {
        filterConditions.year_id = { [Op.eq]: cleanParams.year_id };
    }
  }

  if (cleanParams.display_name) {
    filterConditions.display_name = {
      [Op.like]: `%${cleanParams.display_name}%`,
    };
  }

  if (cleanParams.enabled) {
    filterConditions.enabled = {
      [Op.eq]: cleanParams.enabled === "1" ? true : false,
    };
  }

  try {
    const periods = await dbSAPPS.Period.findAll({
      where: filterConditions,
      order: [["modified", "DESC"]],
      include: [
        {
          model: dbSAPPS.Year,
          as: "year",
          attributes: ["id", "display_name"],
        },
      ]
    });

    return {
      success: true,
      periods,
      message: "periods loaded successfully!",
    };
  } catch (error) {
    console.error("Error retrieving periods: ", error);
    const errorMessage =
      error.message || "Failed to retrieve periods. Please try again later.";
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function option() {
  try {
    const periods = await dbSAPPS.Period.findAll({
      attributes: ["id", "display_name", "start_date", "end_date", "year_id"],
      where: { enabled: true },
      order: [["start_date", "ASC"]],
      include: [
        {
          model: dbSAPPS.Year,
          as: "year",
          attributes: ["id", "display_name"],
        },
      ]
    });

    return {
      success: true,
      periods,
      message: "Periods loaded successfully!",
    };
  } catch (error) {
    console.error("Error retrieving periods: ", error);
    const errorMessage =
      error.message || "Failed to retrieve periods. Please try again later.";
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function count() {
  try {
    const count = await dbSAPPS.Period.count({
      where: { enabled: true },
    });

    return {
      success: true,
      count,
      message: "Periods loaded successfully!",
    };
  } catch (error) {
    console.error("Error counting periods: ", error);
    return {
      success: false,
      message: "Failed to retrieve periods count. Please try again later.",
    };
  }
}

async function create(params) {
  try {
    if (!params.year_id)
      return {
        success: false,
        message: "Year is required!",
      };

    const existingPeriod = await dbSAPPS.Period.findOne({
      where: {
        year_id: params.year_id,
        display_name: params.display_name,
        start_date: params.start_date,
        end_date: params.end_date,
      },
    });
    if (existingPeriod)
      return {
        success: false,
        message: `Period of "${params.display_name}" is already taken.`,
      };

    if (!params.enabled) params.enabled = true;

    // validasi jika start_date lebih dari end_date
    if (params.start_date > params.end_date) {
      return {
        success: false,
        message: "Start date cannot be greater than end date.",
      };
    }

    const newPeriod = await dbSAPPS.Period.create(params);

    return {
      success: true,
      message: "Data period has been successfully adeded!",
      period: newPeriod,
    };
  } catch (error) {
    const errorMessage =
      error.message || "An error occurred during period creation.";
    return {
      success: false,
      message: errorMessage,
    };
  }
}

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

    if (params.year && params.year !== period.year_id && params.display_name && params.display_name !== period.display_name && params.start_date && params.start_date !== period.start_date && params.end_date && params.end_date !== period.end_date) {
      const existingPeriod = await dbSAPPS.Period.findOne({
        where: { year_id: params.year, display_name: params.display_name, start_date: params.start_date, end_date: params.end_date },
      });
      if (existingPeriod) {
        return {
          success: false,
          message: `Period of "${params.display_name}" is already taken. Try again!`,
        };
      }
    }

    await period.update(params);

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

async function enabled(id, params) {
  try {
    const period = await dbSAPPS.Period.findByPk(id);
    if (!period)
      return {
        success: false,
        message: "ClientType 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;

    await period.update(updateData);

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

async function _delete(id) {
  try {
    const period = await dbSAPPS.Period.findByPk(id);
    if (!period) return { success: false, message: "period not found!" };

    await period.destroy();

    return {
      success: true,
      message: "period successfully deleted!",
    };
  } catch (error) {
    const errorMessage = error.message || "Failed to delete period.";
    return {
      success: false,
      message: errorMessage,
    };
  }
}
