const CreditDateLimit = require("../../models/CreditDateLimit");
const CreditLimit = require("../../models/CreditLimit");
const Rpaf = require("../../models/Rpaf");
const { formatDate } = require("../../util/date");
const marketplace = require("../../marketplace.json");
const Customers = require("../../models/Customers");
const { default: axios } = require("axios");
const { pdfBuilder } = require("../../helpers/pdfBuilder");
const emailBuilder = require("../../helpers/transporter");
const { ASSETS_BUILDCREDIT_URL } = require("../../marketplace.json");
const { Op } = require("sequelize");
const { getBuildCreditBalance } = require("../../helpers/buildcredit");
exports.getCustomerCreditLimit = async (req, res, next) => {
  try {
    const creditLimits = await CreditLimit.findAll();

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

exports.getCustomerCreditTerms = async (req, res, next) => {
  try {
    const creditDateLimits = await CreditDateLimit.findAll();

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

exports.buildCreditSubmission1 = async (req, res, next) => {
  try {
    const {
      creditLimit,
      creditTerms,
      companyName,
      companyEmail,
      contactPerson,
      mobilePhone,
      alternativeMobilePhone,
      landline,
      area,
      companyCity,
      companyBrgy,
      addressLine1,
      addressLine2,
      additionalInformation,
      ownerName,
      ownerMobilePhone,
      islandGroup,
      homeProvince,
      homeCity,
      homeBrgy,
      homeLine1,
      homeLine2,
    } = req.body;

    const { customerId } = req;

    const existingBuildCredit = await Rpaf.findOne({
      where: {
        customer_id: customerId,
      },
    });

    const customerAddress = `${addressLine1}, ${companyBrgy}, ${companyCity}, ${area}`;

    if (existingBuildCredit) {
      existingBuildCredit.credit_limit = creditLimit;
      existingBuildCredit.credit_date_limit = creditTerms;
      existingBuildCredit.company_name = companyName;
      existingBuildCredit.company_email = companyEmail;
      existingBuildCredit.contact_person = contactPerson;
      existingBuildCredit.phone = mobilePhone;
      existingBuildCredit.addtl_phone = alternativeMobilePhone;
      existingBuildCredit.landline = landline;
      existingBuildCredit.islandGroup = islandGroup;
      existingBuildCredit.area = area;
      existingBuildCredit.city = companyCity;
      existingBuildCredit.barangay = companyBrgy;
      existingBuildCredit.address = customerAddress;
      existingBuildCredit.address_line_1 = addressLine1;
      existingBuildCredit.address_line_2 = addressLine2;
      existingBuildCredit.addi_information = additionalInformation;
      existingBuildCredit.date_drafted = new Date();
      existingBuildCredit.owner_name = ownerName;
      existingBuildCredit.owner_mobile_number = ownerMobilePhone;
      existingBuildCredit.homeProvince = homeProvince;
      existingBuildCredit.homeCity = homeCity;
      existingBuildCredit.homeBrgy = homeBrgy;
      existingBuildCredit.homeLine1 = homeLine1;
      existingBuildCredit.homeLine2 = homeLine2;
      existingBuildCredit.status = "Draft";
      await existingBuildCredit.save();

      return res.status(200).json({ success: true });
    }

    await Rpaf.create({
      customer_id: customerId,
      credit_limit: creditLimit,
      credit_date_limit: creditTerms,
      company_name: companyName,
      company_email: companyEmail,
      contact_person: contactPerson,
      phone: mobilePhone,
      addtl_phone: alternativeMobilePhone,
      landline: landline,
      islandGroup: islandGroup,
      area: area,
      city: companyCity,
      barangay: companyBrgy,
      address_line_1: addressLine1,
      address_line_2: addressLine2,
      address: customerAddress,
      addi_information: additionalInformation,
      date_drafted: new Date(),
      owner_name: ownerName,
      owner_mobile_number: ownerMobilePhone,
      homeProvince: homeProvince,
      homeCity: homeCity,
      homeBrgy: homeBrgy,
      homeLine1: homeLine1,
      homeLine2: homeLine2,
      status: "Draft",
    });

    return res.status(201).json({ success: true });
  } catch (err) {
    next(err);
  }
};

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

    const existingBuildCredit = await Rpaf.findOne({
      where: {
        customer_id: customerId,
      },
    });

    if (existingBuildCredit) {
      const response = {
        creditLimit: existingBuildCredit.credit_limit,
        creditTerms: existingBuildCredit.credit_date_limit,
        companyName: existingBuildCredit.company_name,
        companyEmail: existingBuildCredit.company_email,
        contactPerson: existingBuildCredit.contact_person,
        mobilePhone: existingBuildCredit.phone,
        alternativeMobilePhone: existingBuildCredit.addtl_phone,
        landline: existingBuildCredit.landline,
        islandGroup: existingBuildCredit.islandGroup,
        area: existingBuildCredit.area,
        companyCity: existingBuildCredit.city,
        companyBrgy: existingBuildCredit.barangay,
        addressLine1: existingBuildCredit.address_line_1,
        addressLine2: existingBuildCredit.address_line_2,
        additionalInformation: existingBuildCredit.addi_information,
        ownerName: existingBuildCredit.owner_name,
        ownerMobilePhone: existingBuildCredit.owner_mobile_number,
        homeProvince: existingBuildCredit.homeProvince,
        homeCity: existingBuildCredit.homeCity,
        homeBrgy: existingBuildCredit.homeBrgy,
        homeLine1: existingBuildCredit.homeLine1,
        homeLine2: existingBuildCredit.homeLine2,
      };

      res.status(200).json({ success: true, form_1: response });
    }

    res.status(200).json({ success: false });
  } catch (err) {
    next(err);
  }
};

exports.buildCreditSubmission2 = async (req, res, next) => {
  const {
    bankName,
    bankBranchName,
    bankAccountName,
    bankAccountNumber,
    bankMgrFirstName,
    bankMgrLastName,
    bankMgrPhoneNumber,
    bankEmail,
    tradeRefCompanyName,
    tradeCompanyArea,
    tradeCompanyCity,
    tradeCompanyBrgy,
    tradeCompanyAddressLine1,
    tradeCompanyAddressLine2,
    tradeCompanyPostCode,
    tradeCompanyPhone,
    tradeDateOfAccountOpening,
    tradeCustomerPhone,
  } = req.body;

  const { customerId } = req;

  const existingBuildCredit = await Rpaf.findOne({
    where: {
      customer_id: customerId,
    },
  });

  if (!existingBuildCredit) return res.status(200).json({ success: false });

  const mergedBankMgrName = `${bankMgrFirstName} ${bankMgrLastName}`;
  const mergedAddress = `${tradeCompanyAddressLine1}, ${tradeCompanyBrgy}, ${tradeCompanyCity}, ${tradeCompanyArea}, ${tradeCompanyPostCode}`;

  existingBuildCredit.bankName = bankName;
  existingBuildCredit.bankBranchName = bankBranchName;
  existingBuildCredit.bankAccountName = bankAccountName;
  existingBuildCredit.bankAccNum = bankAccountNumber;
  existingBuildCredit.bankManagerName = mergedBankMgrName;
  existingBuildCredit.bankManagerPhone = bankMgrPhoneNumber;
  existingBuildCredit.bankEmail = bankEmail;
  existingBuildCredit.company__name = tradeRefCompanyName;
  existingBuildCredit.phone2 = tradeCompanyPhone;
  existingBuildCredit.phone3 = tradeCustomerPhone;
  existingBuildCredit.account_opened = tradeDateOfAccountOpening
    ? formatDate(tradeDateOfAccountOpening)
    : null;
  existingBuildCredit.address2 = mergedAddress;

  existingBuildCredit.trade_company_area = tradeCompanyArea;
  existingBuildCredit.trade_company_city = tradeCompanyCity;
  existingBuildCredit.trade_company_brgy = tradeCompanyBrgy;
  existingBuildCredit.trade_company_address_line_1 = tradeCompanyAddressLine1;
  existingBuildCredit.trade_company_address_line_2 = tradeCompanyAddressLine2;
  existingBuildCredit.trade_company_postcode = tradeCompanyPostCode;
  existingBuildCredit.bank_manager_first_name = bankMgrFirstName;
  existingBuildCredit.bank_manager_last_name = bankMgrLastName;
  existingBuildCredit.date_drafted = new Date();

  await existingBuildCredit.save();

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

exports.buildCreditSubmissionFiles2 = async (req, res, next) => {
  const {
    storeHardware,
    birForm,
    businessPermit,
    dtiRegistration,
    governmentId,
    bankAuthorization,
    otherRelevant,
    creditApprovalForm,
    bankStatement,
    tin,
  } = req.files;

  const { customerId } = req;

  try {
    const existingBuildCredit = await Rpaf.findOne({
      where: { customer_id: customerId },
    });

    if (!existingBuildCredit) return res.status(200).json({ success: false });

    const fileExtractor = (file) => {
      return file && Array.isArray(file) && file.length > 0
        ? file[0].filename
        : null;
    };

    const updates = {
      storeFileName: fileExtractor(storeHardware),
      birFile: fileExtractor(birForm),
      mayorFileName: fileExtractor(businessPermit),
      dtiFileName: fileExtractor(dtiRegistration),
      bankFileName: fileExtractor(bankStatement),
      bankAuthorizationFile: fileExtractor(bankAuthorization),
      otherFileName: fileExtractor(otherRelevant),
      approvalFileName: fileExtractor(creditApprovalForm),
      govFileName: fileExtractor(governmentId),
      tinFileName: fileExtractor(tin),
    };

    for (const [key, value] of Object.entries(updates)) {
      if (value) {
        existingBuildCredit[key] = value;
      }
    }

    await existingBuildCredit.save();

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

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

    const existingBuildCredit = await Rpaf.findOne({
      where: {
        customer_id: customerId,
      },
    });

    if (existingBuildCredit) {
      const response = {
        bankName: existingBuildCredit.bankName,
        bankBranchName: existingBuildCredit.bankBranchName,
        bankAccountName: existingBuildCredit.bankAccountName,
        bankAccountNumber: existingBuildCredit.bankAccNum,
        bankMgrFirstName: existingBuildCredit.bank_manager_first_name,
        bankMgrLastName: existingBuildCredit.bank_manager_last_name,
        bankMgrPhoneNumber: existingBuildCredit.bankManagerPhone,
        bankEmail: existingBuildCredit.bankEmail,
        tradeRefCompanyName: existingBuildCredit.company__name,
        tradeCompanyArea: existingBuildCredit.trade_company_area,
        tradeCompanyCity: existingBuildCredit.trade_company_city,
        tradeCompanyBrgy: existingBuildCredit.trade_company_brgy,
        tradeCompanyAddressLine1:
          existingBuildCredit.trade_company_address_line_1,
        tradeCompanyAddressLine2:
          existingBuildCredit.trade_company_address_line_2,
        tradeCompanyPostCode: existingBuildCredit.trade_company_postcode,
        tradeCompanyPhone: existingBuildCredit.phone2,
        tradeDateOfAccountOpening: existingBuildCredit.account_opened,
        tradeCustomerPhone: existingBuildCredit.phone3,
      };

      return res.status(200).json({ success: true, form_2: response });
    }
    res.status(200).json({ success: false });
  } catch (err) {
    next(err);
  }
};

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

  try {
    const existingBuildCredit = await Rpaf.findOne({
      where: {
        customer_id: customerId,
      },
    });

    const fileExtractor = (file) => {
      if (file && file !== "") {
        return `${marketplace.ASSETS_BUILDCREDIT_URL}${file}`;
      }
      return null;
    };
    if (existingBuildCredit) {
      const response = {
        storeHardware: fileExtractor(existingBuildCredit.storeFileName),
        birForm: fileExtractor(existingBuildCredit.birFile),
        businessPermit: fileExtractor(existingBuildCredit.mayorFileName),
        dtiRegistration: fileExtractor(existingBuildCredit.dtiFileName),
        governmentId: fileExtractor(existingBuildCredit.bankFileName),
        bankAuthorization: fileExtractor(
          existingBuildCredit.bankAuthorizationFile,
        ),
        otherRelevant: fileExtractor(existingBuildCredit.otherFileName),
        creditApprovalForm: fileExtractor(existingBuildCredit.approvalFileName),
        bankStatement: fileExtractor(existingBuildCredit.govFileName),
        tin: fileExtractor(existingBuildCredit.tinFileName),
      };
      res.status(200).json({ success: true, form_2: response });
    }
    res.status(200).json({ success: false });
  } catch (err) {
    next(err);
  }
};

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

    if (!applicantSignature) return res.status(200).json({ success: false });

    const existingBuildCredit = await Rpaf.findOne({
      where: { customer_id: customerId },
    });

    if (!existingBuildCredit) return res.status(200).json({ success: false });

    const fileExtractor = (file) => {
      return file && Array.isArray(file) && file.length > 0
        ? file[0].filename
        : null;
    };

    existingBuildCredit.applicant_signature = fileExtractor(applicantSignature);
    existingBuildCredit.date_drafted = new Date();

    await existingBuildCredit.save();

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

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

  try {
    const existingBuildCredit = await Rpaf.findOne({
      where: {
        customer_id: customerId,
      },
    });

    const fileExtractor = (file) => {
      if (file && file !== "") {
        return `${marketplace.ASSETS_BUILDCREDIT_URL}${file}`;
      }
      return null;
    };
    if (existingBuildCredit) {
      const response = {
        applicantSignature: fileExtractor(
          existingBuildCredit.applicant_signature,
        ),
      };
      res.status(200).json({ success: true, form_3: response });
    }
    res.status(200).json({ success: false });
  } catch (err) {
    next(err);
  }
};

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

  try {
    const { status } = req.body;

    const validStatus = ["Draft", "Pending"];
    if (!status || !validStatus.includes(status)) {
      return res.status(200).json({ success: false });
    }

    const existingBuildCredit = await Rpaf.findOne({
      where: { customer_id: customerId },
    });

    if (!existingBuildCredit) {
      return res.status(200).json({ success: false });
    }

    existingBuildCredit.status = status;
    if (status === "Pending") existingBuildCredit.date_submitted = new Date();
    await existingBuildCredit.save();

    // TODO: Email
    if (status === "Pending") await sendBuildCreditMail(customerId);

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

const sendBuildCreditMail = async (customerId) => {
  try {
    const buildCreditRecord = await Rpaf.findOne({
      where: {
        customer_id: customerId,
        status: "Pending",
      },
      include: [
        {
          model: Customers,
          as: "customer_detail",
        },
      ],
    });

    if (!buildCreditRecord) return false;

    const {
      company_name,
      bankBranchName,
      bankAccountName,
      bankAccNum,
      applicant_signature,
      bankEmail,
      customer_detail,
    } = buildCreditRecord;

    const date = new Date();
    const dateOptions = {
      weekday: undefined,
      year: "numeric",
      month: "long",
      day: "numeric",
      hour: "numeric",
      minute: "numeric",
      hour12: true,
    };
    const formattedDate = date.toLocaleString("en-US", dateOptions);

    const axiosResponse = await axios.get(
      `${ASSETS_BUILDCREDIT_URL}${applicant_signature}`,
      {
        responseType: "arraybuffer",
      },
    );
    const imageBase64 = Buffer.from(axiosResponse.data, "binary").toString(
      "base64",
    );
    const templatePath =
      __dirname + "/../../helpers/email-templates/buildcredit.html";

    const data = {
      date: formattedDate,
      compName: company_name,
      bankBranch: bankBranchName,
      accName: bankAccountName,
      accNum: bankAccNum,
      signatory: `${customer_detail.first_name} ${customer_detail.last_name}`,
      signature: imageBase64,
      name: `${customer_detail.first_name} ${customer_detail.last_name}`,
    };
    const pdfResponse = await pdfBuilder(
      templatePath,
      "build-credit-letter",
      "pdf-files",
      "portrait",
      data,
    );
    const receivers = [bankEmail];
    const ccs = [];
    const attachments = [
      {
        filename: pdfResponse.file_name,
        path: pdfResponse.file_path,
        contentType: "application/pdf",
      },
    ];

    if (receivers.length > 0) {
      const emailResponse = await emailBuilder(
        receivers,
        ccs,
        "Build Credit Authorization Letter",
        false,
        "",
        attachments,
      );
      return true;
    } else {
      return false;
    }
  } catch (err) {
    console.log(err);
    return false;
  }
};

// Buildcredit.ph

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

  console.log("Fetching build credit details for customer ID:", customerId);

  try {
    const buildCreditRecordPromise = Rpaf.findOne({
      where: {
        customer_id: customerId,
        status: {
          [Op.notIn]: [
            "Draft",
            "Pending",
            "Pending - Waiting for other requirements",
          ],
        },
      },
    });

    const buildCreditBalancePromise = getBuildCreditBalance(customerId, true);

    const [buildCreditRecord, buildCreditBalance] = await Promise.all([
      buildCreditRecordPromise,
      buildCreditBalancePromise,
    ]);

    if (!buildCreditRecord) {
      return res.status(200).json({ success: false });
    }

    const apiResponse = {
      buildCreditAccountId: `BC-${buildCreditRecord.id}`,
      accountId: customerId,
      companyName: buildCreditRecord.company_name,
      creditLimit: buildCreditRecord.credit_limit,
      creditTerms: buildCreditRecord.credit_date_limit,
      bankName: buildCreditRecord.bankName,
      bankBranchName: buildCreditRecord.bankBranchName,
      bankAccountNumber: buildCreditRecord.bankAccNum,
      ownerName: buildCreditRecord.owner_name,
      status: buildCreditRecord.status,
      balance: buildCreditBalance,
    };

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