const Rpaf = require("../../models/Rpaf");
const RpafPayment = require("../../models/RpafPayment");
const OrderForm = require("../../models/OrderForm");
const Sequelize = require("sequelize");
const SellersCompany = require("../../models/SellersCompany");
const SplitPayment = require("../../models/SplitPayments");
const errorHandler = require("../../util/errorHandler");

const {
  generateRandomString,
  generateSecureRandomSixDigit,
  getCurrentDateTimeInGMT8,
} = require("../../helpers/common");
const { formatDate } = require("../../util/date");

exports.getBuildCreditOrders = async (req, res, next) => {
  try {
    const { customerId } = req;

    const buildcreditOrders = await OrderForm.findAll({
      where: {
        customer_id: customerId,
        payment_method: { [Sequelize.Op.or]: ["RPAF", "Split", "Build Credit"] },
        status: { [Sequelize.Op.ne]: "Denied" },
      },
      include: [
        {
          model: SellersCompany,
          as: "sellers_company_details",
          attributes: ["id", "shop_name", "company_name"],
        },
      ],
      attributes: [
        "id",
        "payment_method",
        "status",
        "reference_no",
        "split_payment_id",
        "total_amount",
        "date_created",
        "seller_id",
      ],
    });

    const response = await Promise.all(
      buildcreditOrders.map(async (buildCredit) => {
        const payment = await RpafPayment.findAll({
          where: {
            customer_id: customerId,
            order_id: buildCredit.reference_no,
            status: "Verified",
          },
          attributes: [[Sequelize.fn("SUM", Sequelize.col("amount_paid")), "sum_amount_paid"]],
          raw: true,
        });

        const _payment = await RpafPayment.findAll({
          where: {
            customer_id: customerId,
            order_id: buildCredit.reference_no,
          },
          attributes: ["id", "reference_no", "order_id", "amount_paid", "file_attach", "date", "status"],
        });

        let amountPaid = payment.length > 0 ? payment[0].sum_amount_paid : 0;
        let unpaid_balance = parseFloat(buildCredit.total_amount) - parseFloat(amountPaid || 0);
        let splitPayment;
        if (buildCredit.payment_method === "Split") {
          splitPayment = await SplitPayment.findOne({
            where: {
              id: buildCredit.split_payment_id,
            },
          });
          unpaid_balance = parseFloat(splitPayment.rpaf_payment) - parseFloat(amountPaid || 0);
        }

        const modifiedPaymentsResponse = _payment.map((payment) => ({
          id: payment.id,
          reference_no: payment.reference_no,
          amount_paid: payment.amount_paid,
          file_attach: payment.file_attach
            ? `https://api.buildhubware.com/public/rpaf-payment/${payment.file_attach}`
            : null,
          date: payment.date,
          status: payment.status,
        }));

        return {
          id: buildCredit.id,
          payment_method: buildCredit.payment_method,
          status: buildCredit.status,
          reference_no: buildCredit.reference_no,
          total_amount: buildCredit.payment_method === "Split" ? splitPayment.rpaf_payment : buildCredit.total_amount,
          amount_paid: amountPaid || 0,
          unpaid_balance,
          payments: modifiedPaymentsResponse,
          date_created: buildCredit.date_created,
          seller_id: buildCredit.seller_id,
          sellers_company: buildCredit.sellers_company_details,
        };
      })
    );

    res.status(200).json({ success: true, response });
  } catch (error) {
    next(error);
  }
};

exports.buildreditPayment = async (req, res, next) => {
  const { customerId } = req;
  const { data } = req.body;
  const { order_id, amount_paid, online_payment = "false" } = data;
  const { rpafpaymentPhoto } = req.files;

  const isOnlinePayment = online_payment === "true";

  try {
    if (!isOnlinePayment) {
      if (!rpafpaymentPhoto) return res.status(401).json({ success: false, message: "Invalid attachment" });
    }
    const orderForm = await OrderForm.findOne({
      where: {
        reference_no: order_id,
        customer_id: customerId,
      },
    });
    if (!orderForm) return res.status(401).json({ success: false, message: "Invalid order id" });
    const reference_no = "RPREF" + Math.random().toString(36).substring(2, 10).toUpperCase();
    const payment = await RpafPayment.create({
      reference_no,
      customer_id: customerId,
      order_id,
      amount_paid,
      file_attach: isOnlinePayment ? null : rpafpaymentPhoto[0].filename,
      status: "Pending",
    });

    res.status(201).json({ success: true, payment });
  } catch (error) {
    next(error);
  }
};

exports.externalBuildCreditApplication = async (req, res, next) => {
  const {
    creditLimit,
    creditTerms,
    companyName,
    companyEmail,
    contactPerson,
    mobilePhone,
    altMobilePhone,
    landline,
    area,
    address,
    city,
    barangay,
    address_line_1,
    address_line_2,
    additional_info,
    owner_name = "",
    owner_mobile_number = "",
  } = req.body;

  const externalSourceId = `${generateRandomString()}${generateSecureRandomSixDigit()}`;
  const currentDateTime = await getCurrentDateTimeInGMT8();

  const createJSON = {
    customer_id: 0,
    status: "Pending",
    credit_limit: creditLimit,
    credit_date_limit: creditTerms,
    company_name: companyName,
    contact_person: contactPerson,
    company_email: companyEmail,
    phone: mobilePhone,
    addtl_phone: altMobilePhone,
    landline: landline,
    area: area,
    address: address,
    city,
    barangay,
    address_line_1,
    address_line_2,
    addi_information: additional_info,
    date_drafted: currentDateTime,
    owner_name: owner_name,
    owner_mobile_number: owner_mobile_number,
    external_source_id: externalSourceId,
    form_source: "BuildCredit",
  };

  const filteredUpdateJson = Object.fromEntries(
    Object.entries(createJSON).filter(([_, value]) => value != null && value !== "")
  );

  try {
    const buildCredit = await Rpaf.create(filteredUpdateJson);
    res.status(200).json({ success: true, build_credit: { id: buildCredit.id, source_id: externalSourceId } });
  } catch (err) {
    next(err);
  }
};

function fileChecker(file) {
  if (file && Array.isArray(file) && file.length > 0) {
    return file[0].filename;
  } else {
    return null;
  }
}

exports.externalBuildCreditApplication2 = async (req, res, next) => {
  const { data } = req.body;
  const {
    bankName,
    bankBranchName,
    bankAccountName,
    bankAccountNo,
    bankManagerName,
    bankManagerPhone,
    bankEmail,
    companyNameTR,
    addressTR,
    companyPhone,
    dateAccountOpenedTR,
    customerPhone,
    source_id,
  } = data;

  const {
    storeFile,
    birFile,
    businessPermitFile,
    dtiSecRegistrationFile,
    bankStatementPassbookFile,
    bankAuthorizationFile,
    otherFile,
    creditApprovalFile,
    govIdFile,
    tinFile,
  } = req.files;

  if (!source_id || source_id === "") {
    return errorHandler("Source ID Missing from the request!", 401);
  }

  if (!req.files || !req.files.storeFile) {
    return errorHandler("Store/Hardware is missing from the request.", 500);
  }
  if (!req.files || !req.files.birFile) {
    return errorHandler("BIR Form/Certificate of Registration is missing from the request.", 500);
  }
  if (!req.files || !req.files.businessPermitFile) {
    return errorHandler("Business Permit is missing from the request.", 500);
  }
  if (!req.files || !req.files.govIdFile) {
    return errorHandler("Government Id is missing from the request.", 500);
  }
  if (!req.files || !req.files.dtiSecRegistrationFile) {
    return errorHandler("DTI/SEC Registration is missing from the request.", 500);
  }

  const updateJson = {
    storeFileName: fileChecker(storeFile),
    birFile: fileChecker(birFile),
    mayorFileName: fileChecker(businessPermitFile),
    dtiFileName: fileChecker(dtiSecRegistrationFile),
    bankFileName: fileChecker(bankStatementPassbookFile),
    bankAuthorizationFile: fileChecker(bankAuthorizationFile),
    otherFileName: fileChecker(otherFile),
    approvalFileName: fileChecker(creditApprovalFile),
    govFileName: fileChecker(govIdFile),
    tinFileName: fileChecker(tinFile),

    bankName: bankName,
    bankBranchName: bankBranchName,
    bankAccountName: bankAccountName,
    bankAccNum: bankAccountNo,
    bankManagerName: bankManagerName,
    bankManagerPhone: bankManagerPhone,
    bankEmail: bankEmail,
    company__name: companyNameTR,
    address2: addressTR,
    phone2: companyPhone,
    account_opened: formatDate(dateAccountOpenedTR),
    phone3: customerPhone,
  };

  try {
    const sourceIdChecking = await Rpaf.findOne({
      where: {
        external_source_id: source_id,
      },
    });

    if (!sourceIdChecking) return errorHandler("Source ID not valid!", 401);

    const filteredUpdateJson = Object.fromEntries(
      Object.entries(updateJson).filter(([_, value]) => value != null && value !== "")
    );

    // Update Data
    await Rpaf.update(filteredUpdateJson, {
      where: {
        external_source_id: source_id,
      },
    });

    // Query Data
    const buildCreditUpdated = await Rpaf.findOne({
      where: {
        external_source_id: source_id,
      },
    });

    res.status(200).json({
      success: true,
      buildcredit: { id: buildCreditUpdated.id, source_id: buildCreditUpdated.external_source_id },
    });
  } catch (err) {
    next(err);
  }
};

exports.externalBuildCreditApplication3 = async (req, res, next) => {
  const { data } = req.body;
  const { agentEmail, agentCode, source_id } = data;

  const { applicantSignature } = req.files;

  if (!req.files || !req.files.applicantSignature) {
    return errorHandler("Signature is missing from the request.", 401);
  }

  if (!source_id || source_id === "") {
    return errorHandler("Source ID Missing from the request!", 401);
  }

  try {
    const sourceIdChecking = await Rpaf.findOne({
      where: {
        external_source_id: source_id,
      },
    });

    if (!sourceIdChecking) return errorHandler("Source ID not valid!", 401);

    const updateJson = {
      applicant_signature: fileChecker(applicantSignature),
      agent_email: agentEmail,
      agent_code: agentCode,
    };

    const filteredUpdateJson = Object.fromEntries(
      Object.entries(updateJson).filter(([_, value]) => value != null && value !== "")
    );
    await Rpaf.update(filteredUpdateJson, {
      where: {
        external_source_id: source_id,
      },
    });

    const buildCredit = await Rpaf.findOne({
      where: {
        external_source_id: source_id,
      },
    });
    res.status(200).json({
      success: true,
      buildcredit: {
        id: buildCredit.id,
        source_id: buildCredit.external_source_id,
      },
    });
  } catch (err) {
    next(err);
  }
};

function fileExtractorPlusLink(fileName) {
  if (fileName && fileName !== null && fileName !== "") {
    return {
      raw: fileName,
      link: `https://api.buildhubware.com/public/rpaf-build-credit-application-upload/${fileName}`,
    };
  } else {
    return null;
  }
}

exports.findExternalBuildCreditApplicationBySourceId = async (req, res, next) => {
  try {
    const { source_id } = req.params;

    const buildCredit = await Rpaf.findOne({
      where: {
        external_source_id: source_id,
      },
    });

    const responseJson = {
      id: buildCredit.id,
      status: buildCredit.status,
      remarks: buildCredit.remarks,
      agent_email: buildCredit.agent_email,
      agent_code: buildCredit.agent_code,

      // FILES
      files: {
        signature: fileExtractorPlusLink(buildCredit.applicant_signature),
        store: fileExtractorPlusLink(buildCredit.storeFileName),
        bir: fileExtractorPlusLink(buildCredit.birFile),
        mayor: fileExtractorPlusLink(buildCredit.mayorFileName),
        dti: fileExtractorPlusLink(buildCredit.dtiFileName),
        bank: fileExtractorPlusLink(buildCredit.bankFileName),
        bank_authorization: fileExtractorPlusLink(buildCredit.bankAuthorizationFile),
        other: fileExtractorPlusLink(buildCredit.otherFileName),
        approval: fileExtractorPlusLink(buildCredit.approvalFileName),
        government: fileExtractorPlusLink(buildCredit.govFileName),
        tin: fileExtractorPlusLink(buildCredit.tinFileName),
      },

      credit_limit: buildCredit.credit_limit,
      credit_terms: buildCredit.credit_date_limit,
      company: {
        company: buildCredit.company_name,
        contact_person: buildCredit.contact_person,
        email: buildCredit.company_email,
        phone: buildCredit.phone,
        alt_phone: buildCredit.addtl_phone,
        landline: buildCredit.landline,
        area: buildCredit.area,
        address: buildCredit.address,
      },
      trade_reference: {
        company_name: buildCredit.company__name,
        contact_name: buildCredit.contact__name,
        address: buildCredit.address2,
        phone: buildCredit.phone2,
        account_opened: buildCredit.account_opened,
        alt_phone: buildCredit.phone3,
        city: buildCredit.city,
        barangay: buildCredit.barangay,
        address_line_1: buildCredit.address_line_1,
        address_line_2: buildCredit.address_line_2,
      },

      bank: {
        name: buildCredit.bankName,
        branch: buildCredit.bankBranchName,
        account_name: buildCredit.bankAccountName,
        manager_name: buildCredit.bankManagerName,
        manager_phone: buildCredit.bankManagerPhone,
        account_no: buildCredit.bankAccNum,
        bank_email: buildCredit.bankEmail,
      },
      owner: {
        name: buildCredit.owner_name,
        mobile_number: buildCredit.owner_mobile_number,
      },
      source: {
        id: buildCredit.external_source_id,
        form: buildCredit.form_source,
      },
    };

    res.status(200).json({ success: true, buildCredit: responseJson });
  } catch (err) {
    next(err);
  }
};
