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 outlets = await dbSAPPS.Outlet.findAll({
      order: [["modified", "DESC"]],
      include: [
        {
          model: dbSAPPS.Institution,
          as: "institution",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.OutletType,
          as: "outlettype",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.Company,
          as: "company",
          attributes: ['id', 'display_name',],
        },
        {
          model: dbSAPPS.Province,
          as: "province",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.City,
          as: "city",
          attributes: ['id', 'display_name', 'code'],
        },
      ]
    });

     const dataOutlets = await Promise.all(outlets.map(async (item) => {
          const modifiedBy = await dbSAPPS.User.findOne({where: { id: parseInt(item.modified_by) }, attributes: ['full_name']});
          return {
            ...item.toJSON(),
            modifiedBy: modifiedBy ? modifiedBy.dataValues.full_name : null
          };
        }));

    return {
      outlets : dataOutlets,
      success: true,
      message: "outlets loaded successfully!",
    };
  } catch (error) {
    const errorMessage = error.message || "Failed to load outlets!";
    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];
    }
  });

  // Global search (q): trim dan cari hanya di kolom outlet sendiri agar aman di semua DB/Sequelize
  const qSearch = cleanParams.q != null ? String(cleanParams.q).trim() : "";
  if (qSearch !== "") {
    const qLike = `%${qSearch}%`;
    filterConditions[Op.or] = [
      { display_name: { [Op.like]: qLike } },
      { code: { [Op.like]: qLike } },
      { address: { [Op.like]: qLike } },
    ];
  }

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

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

  if (cleanParams.companiesId && Array.isArray(cleanParams.companiesId) && cleanParams.companiesId.length > 0) {
    filterConditions.company_id = { [Op.in]: cleanParams.companiesId };
  } else if (cleanParams.company_id != null && cleanParams.company_id !== "") {
    const id = parseInt(cleanParams.company_id, 10);
    if (!Number.isNaN(id)) filterConditions.company_id = id;
  }

  if (cleanParams.province_id) {
    filterConditions.province_id = {
      [Op.eq]: cleanParams.province_id,
    };
  }
  
  if (cleanParams.city_id) {
    filterConditions.city_id = {
      [Op.eq]: cleanParams.city_id,
    };
  }

  if (cleanParams.institution_id) {
    filterConditions.institution_id = {
      [Op.eq]: cleanParams.institution_id,
    };
  }

  if (cleanParams.outlettype_id) {
    filterConditions.outlettype_id = {
      [Op.eq]: cleanParams.outlettype_id,
    };
  }

  if (cleanParams.enabled !== undefined && cleanParams.enabled !== null && cleanParams.enabled !== "") {
    filterConditions.enabled = cleanParams.enabled === "1" || cleanParams.enabled === true;
  }

  try {
    const rows = await dbSAPPS.Outlet.findAll({
      where: filterConditions,
      order: [["modified", "DESC"]],
      include: [
        {
          model: dbSAPPS.Institution,
          as: "institution",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.OutletType,
          as: "outlettype",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.Company,
          as: "company",
          attributes: ['id', 'display_name'],
        },
        {
          model: dbSAPPS.Province,
          as: "province",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.City,
          as: "city",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.User,
          attributes: ['id', 'full_name'],
          as: "modifier",
          required: false,
        },
      ]
    });

    const outlets = rows.map((row) => {
      const plain = row.get ? row.get({ plain: true }) : row;
      return { ...plain, modifier: plain.modifier?.full_name ?? null };
    });

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

async function option() {
  try {
    const outlets = await dbSAPPS.Outlet.findAll({
      attributes: ["id", "display_name", "code", "address"],
      where: { enabled: true },
      order: [["display_name", "ASC"]],
      include: [
        {
          model: dbSAPPS.Institution,
          as: "institution",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.OutletType,
          as: "outlettype",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.Company,
          as: "company",
          attributes: ['id', 'display_name'],
        },
        {
          model: dbSAPPS.Province,
          as: "province",
          attributes: ['id', 'display_name', 'code'],
        },
        {
          model: dbSAPPS.City,
          as: "city",
          attributes: ['id', 'display_name', 'code'],
        },
      ]
    });

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

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

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

async function create(params) {
  try {
    if (!params.display_name) {
      return {
        success: false,
        message: "Outlet name",
      };
    }

    const existingNameNumber = await dbSAPPS.Outlet.findOne({
        where: {
          display_name: params.display_name,
          company_id: params.company_id
        },
      });

    if (existingNameNumber)
      return {
        success: false,
        message: `Outlet name "${params.display_name}" is already taken.`,
      };
    
    if (!params.enabled) params.enabled = true;

    // Generate code
    // const codeResult = await generateCode(params);
    // if (!codeResult.success) {
    //   return codeResult; // Kembalikan jika ada kesalahan
    // }

    // params.code = codeResult.code;

    // const existingOutletsCode = await dbSAPPS.Outlet.findOne({ where: { code: params.code } });
    // if (existingOutletsCode) {
    //   return {
    //     success: false,
    //     message: `Outlet code "${params.code}" is already taken. Try again!`,
    //   };
    // }


    const newOutlets = await dbSAPPS.Outlet.create(params);

    // Respons sukses
    return {
      success: true,
      message: "outlets data has been successfully added!",
      outlets: newOutlets,
    };
  } catch (error) {
    const errorMessage = error.message || "An error occurred during create outlets processing.";
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function generateCode(params) {
  try {
    let code = 'O'; // Inisialisasi dengan huruf depan O
    let proviceCode, cityCode, outletTypeCode, institutionCode;

    if (!params.province_id) {
      proviceCode = '00';
    } else {
      const province = await dbSAPPS.Province.findByPk(params.province_id);
      proviceCode = province?.code;
    }

    if (!params.city_id) {
      cityCode = '00';
    } else {
      const city = await dbSAPPS.City.findByPk(params.city_id);
      cityCode = city?.code;
    }

    if (!params.outlettype_id) {
      outletTypeCode = '00';
    } else {
      const outletType = await dbSAPPS.OutletType.findByPk(params.outlettype_id);
      outletTypeCode = outletType?.code;
    }

    if (!params.institution_id) {
      institutionCode = '00';
    } else {
      const institution = await dbSAPPS.Institution.findByPk(params.institution_id);
      institutionCode = institution?.code;
    }

    const lastData = await dbSAPPS.Outlet.findOne({
      order: [['code', 'DESC']],
    });

    // Dapatkan angka increment (4 digit)
    let increment4DigitAngka = '0001';
    if (lastData && lastData.code) {
      const lastIncrement = parseInt(lastData.code.slice(-4), 10); // Ambil 4 digit terakhir
      increment4DigitAngka = (lastIncrement + 1).toString().padStart(4, '0'); // Tambahkan 1 dan pad dengan 0
    }

    // Gabungkan kode akhir
    const newCode =
      code +
      proviceCode +
      cityCode +
      outletTypeCode +
      institutionCode +
      increment4DigitAngka;

    params.code = newCode; // Set kode ke params

    return { success: true, code: newCode }; // Kembalikan kode yang dihasilkan
  } catch (error) {
    console.error('Error generating code:', error);
    return { success: false, error: error.message };
  }
}

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

    if (params.display_name && params.display_name !== outlets.display_name) {
      const existingOutletsName = await dbSAPPS.Outlet.findOne({
        where: { display_name: params.display_name, company_id: params.company_id },
      });
      if (existingOutletsName) {
        return {
          success: false,
          message: `Outlet name "${params.display_name}" is already taken. Try again!`,
        };
      }
    }

     // Generate code
    //  const codeResult = await generateCode(params);
    //  if (!codeResult.success) {
    //    return codeResult; // Kembalikan jika ada kesalahan
    //  }
 
    //  params.code = codeResult.code;

    // if (params.code && params.code !== outlets.code) {
    //   const existingOutletsCode = await dbSAPPS.Outlet.findOne({
    //     where: { code: params.code },
    //   });
    //   if (existingOutletsCode) {
    //     return {
    //       success: false,
    //       message: `Outlets code "${params.code}" is already taken. Try again!`,
    //     };
    //   }
    // }

    await outlets.update(params);

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

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

    await outlets.update(updateData);

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

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

    await outlets.destroy();

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