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

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

async function getAll(params) {
  const filterConditions = {};

  if (params.doc_id) {
    filterConditions.id = params.doc_id;
  }
  try {
    const invoiceReceipts = await dbSAPPS.InvoiceReceipt.findAll({
      where: filterConditions,
      order: [["modified", "DESC"]],
      include: [
        {
          model: dbSAPPS.InvoiceReceiptChild,
          as: "invoicereceiptchilds",
          attributes: [
            "id",
            "invoice_no",
            "tax_invoice_no",
            "invoice_date",
            "amount",
            "due_date",
          ],
        },
        {
          model: dbSAPPS.User,
          as: "user",
          include: [
            {
              model: dbSAPPS.Employee,
              as: "employee",
              attributes: ["employee_name"],
              include: [
                {
                  model: dbSAPPS.Designation,
                  as: "designation",
                  attributes: ["display_name"],
                },
              ],
            },
          ],
        },
        {
          model: dbSAPPS.Company,
          as: "company",
          attributes: ["name"],
        },
      ],
    });

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

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

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

  try {
    const invoiceReceipts = await dbSAPPS.InvoiceReceipt.findAll({
      where: filterConditions,
      order: [["modified", "DESC"]], // Opsional: Mengurutkan hasil berdasarkan kolom 'modified'
      include: [
        {
          model: dbSAPPS.InvoiceReceiptChild,
          as: "invoicereceiptchilds",
          attributes: [
            "id",
            "invoice_no",
            "tax_invoice_no",
            "invoice_date",
            "amount",
            "due_date",
          ],
        },
        {
          model: dbSAPPS.User,
          as: "user",
          include: [
            {
              model: dbSAPPS.Employee,
              as: "employee",
              attributes: ["employee_name"],
              include: [
                {
                  model: dbSAPPS.Designation,
                  as: "designation",
                  attributes: ["display_name"],
                },
              ],
            },
          ],
        },
        {
          model: dbSAPPS.Company,
          as: "company",
          attributes: ["name"],
        },
      ],
    });

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

async function option() {
  try {
    const invoiceReceipts = await dbSAPPS.InvoiceReceipt.findAll({
      attributes: ["id", "receipt_no"],
      where: { enabled: true },
      order: [["receipt_no", "ASC"]],
      include: [
        {
          model: dbSAPPS.InvoiceReceiptChild,
          as: "invoicereceiptchilds",
          attributes: [
            "id",
            "invoice_no",
            "tax_invoice_no",
            "invoice_date",
            "amount",
            "due_date",
          ],
        },
        {
          model: dbSAPPS.User,
          as: "user",
          include: [
            {
              model: dbSAPPS.Employee,
              as: "employee",
              attributes: ["employee_name"],
              include: [
                {
                  model: dbSAPPS.Designation,
                  as: "designation",
                  attributes: ["display_name"],
                },
              ],
            },
          ],
        },
        {
          model: dbSAPPS.Company,
          as: "company",
          attributes: ["name"],
        },
      ],
    });

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

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

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

async function create(params) {
  const transaction = await dbSAPPS.sequelize.transaction();
  try {
    // Validasi parameter yang diperlukan
    if (!params.company_id) {
      return {
        success: false,
        message: "Company is required!",
      };
    }

    const toRoman = (month) => {
      const romanNumerals = [
        "I",
        "II",
        "III",
        "IV",
        "V",
        "VI",
        "VII",
        "VIII",
        "IX",
        "X",
        "XI",
        "XII",
      ];
      return romanNumerals[month - 1];
    };

    const generateNextNumber = async (transaction) => {
      const date = new Date(params.date);
      const month = date.getMonth() + 1; // getMonth() returns 0-11
      const year = date.getFullYear();
      const yearShort = year.toString().slice(-2);
      const monthRoman = toRoman(month);

      const prefix = `/SAP/TT/FA/${monthRoman}/${yearShort}`;

      // Cari dokumen dengan pola tertentu di bulan dan tahun ini
      const existingDocs = await dbSAPPS.InvoiceReceipt.findAll({
        where: {
          receipt_no: {
            [Op.like]: `%${prefix}`, // Cari yang suffix-nya cocok
          },
        },
        transaction,
      });

      // Ambil nomor urut tertinggi
      let maxNumber = 0;
      existingDocs.forEach((doc) => {
        const parts = doc.receipt_no.split("/");
        const numberPart = parseInt(parts[0], 10); // Ambil bagian "001"
        if (!isNaN(numberPart)) {
          maxNumber = Math.max(maxNumber, numberPart);
        }
      });

      const nextNumber = (maxNumber + 1).toString().padStart(3, "0");

      return `${nextNumber}${prefix}`;
    };

    // Generate the new number
    const newNumber = await generateNextNumber();
    const newParams = {
      ...params,
      receipt_no: newNumber,
    };

    // Cek apakah Invoice Receipt sudah ada
    const existingInvoiceReceipt = await dbSAPPS.InvoiceReceipt.findOne({
      where: {
        receipt_no: params.receipt_no,
      },
    });

    if (existingInvoiceReceipt) {
      return {
        success: false,
        message: `Invoice with "${params.receipt_no}" is already taken.`,
      };
    }

    // Set default value untuk enabled
    if (!params.enabled) params.enabled = true;

    // Buat Invoice Receipt baru
    const newInvoiceReceipt = await dbSAPPS.InvoiceReceipt.create(newParams, {
      transaction,
    });

    // Proses invoicereceiptchilds jika ada
    if (params.invoicereceiptchilds) {
      // Pastikan data adalah array
      if (typeof params.invoicereceiptchilds === "string") {
        params.invoicereceiptchilds = JSON.parse(params.invoicereceiptchilds);
      }

      // Validasi dan persiapkan data untuk bulkCreate
      const invoiceReceiptsChildData = params.invoicereceiptchilds.map(
        (invoiceReceiptChild) => {
          // Validasi field yang diperlukan
          if (!invoiceReceiptChild.invoice_no) {
            throw new Error(
              "Missing required fields in invoice receipt child."
            );
          }

          return {
            ...invoiceReceiptChild,
            creation: Date.now(),
            modified: Date.now(),
            modified_by: params.modified_by,
            owner: params.owner,
            invoicereceipt_id: newInvoiceReceipt.id,
          };
        }
      );

      // Lakukan bulkCreate
      try {
        await dbSAPPS.InvoiceReceiptChild.bulkCreate(invoiceReceiptsChildData, {
          transaction,
        });
      } catch (bulkCreateError) {
        await transaction.rollback();
        return {
          success: false,
          message:
            "Failed to create invoice receipt child: " +
            bulkCreateError.message,
        };
      }
    }

    // Commit transaksi jika semua berhasil
    await transaction.commit();
    return {
      success: true,
      message: "Data Invoice Receipt has been successfully added!",
      invoiceReceipts: newInvoiceReceipt,
    };
  } catch (error) {
    // Rollback transaksi jika terjadi kesalahan
    await transaction.rollback();
    const errorMessage =
      error.message || "An error occurred during Invoice Receipt creation.";
    console.error("Error creating invoice receipt:", error); // Log kesalahan untuk debugging
    return {
      success: false,
      message: errorMessage,
    };
  }
}

async function update(id, params) {
  const transaction = await dbSAPPS.sequelize.transaction();
  try {
    // Mencari Invoice Receipt berdasarkan ID
    const invoiceReceipt = await dbSAPPS.InvoiceReceipt.findByPk(id);
    if (!invoiceReceipt) {
      return {
        success: false,
        message: "Invoice not found!",
      };
    }

    // Validasi jika delivery_no diubah
    if (params.receipt_no && params.receipt_no !== invoiceReceipt.receipt_no) {
      const existingInvoiceReceiptNo = await dbSAPPS.InvoiceReceipt.findOne({
        where: {
          receipt_no: params.receipt_no,
        },
      });
      if (existingInvoiceReceiptNo) {
        return {
          success: false,
          message: `Invoice with "${params.receipt_no}" is already taken. Try again!`,
        };
      }
    }

    // Update Invoice Receipt
    await invoiceReceipt.update(params, { transaction });

    // Proses invoicereceiptchilds jika ada
    if (params.invoicereceiptchilds) {
      // Pastikan data adalah array
      if (typeof params.invoicereceiptchilds === "string") {
        params.invoicereceiptchilds = JSON.parse(params.invoicereceiptchilds);
      }

      // Hapus child yang ada sebelum menambahkan yang baru
      await dbSAPPS.InvoiceReceiptChild.destroy({
        where: { invoicereceipt_id: id },
        transaction,
      });

      // Persiapkan data untuk bulkCreate
      const invoiceReceiptsChildData = params.invoicereceiptchilds.map(
        (invoiceReceiptChild) => {
          // Validasi field yang diperlukan
          if (!invoiceReceiptChild.invoice_no) {
            throw new Error(
              "Missing required fields in invoice receipt child."
            );
          }

          return {
            ...invoiceReceiptChild,
            creation: Date.now(),
            modified: Date.now(),
            modified_by: params.modified_by,
            owner: params.owner,
            invoicereceipt_id: id, // Mengaitkan dengan ID Invoice Receipt yang diupdate
          };
        }
      );

      // Lakukan bulkCreate untuk child yang baru
      await dbSAPPS.InvoiceReceiptChild.bulkCreate(invoiceReceiptsChildData, {
        transaction,
      });
    }

    await transaction.commit();
    return {
      success: true,
      message: "Your data invoice receipt has been saved!",
    };
  } catch (error) {
    // Rollback transaksi jika terjadi kesalahan
    await transaction.rollback();
    const errorMessage =
      error.message || "Failed to update invoice receipt data.";
    console.error("Error updating invoice receipt:", error); // Log kesalahan untuk debugging
    return {
      success: false,
      message: errorMessage,
    };
  }
}

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

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

async function _delete(id) {
  const transaction = await dbSAPPS.sequelize.transaction();
  try {
    const invoiceReceipt = await dbSAPPS.InvoiceReceipt.findByPk(id);
    if (!invoiceReceipt)
      return { success: false, message: "Invoice Receipt not found!" };

    await new Promise((resolve) => setTimeout(resolve, 500));
    await invoiceReceipt.destroy();
    await transaction.commit();

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