const {
  checkoutService,
  mockCheckoutService,
  mockCheckoutServicev2,
  checkoutPaymentFallbackService,
  availablePaymentMethodService,
} = require("../../helpers/checkout.service");
const QRCode = require("qrcode");
const fs = require("fs");
const path = require("path");
const OrderForm = require("../../models/OrderForm");
const Customers = require("../../models/Customers");
const WebhookCatch = require("../../models/WebhookCatch");

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

    const {
      shipping_type,
      payment_method,
      rpaf_payment,
      bank_payment,
      voucher_code,
      pickup_date,
      order_instructions,
      agent_code,
      transportify_shipping_fee,
      lalamove_shipping_fee,
      lalamove_quotation_id,
      lalamove_customer_stop_id,
      lalamove_seller_stop_id,
      checkoutAddress,
      checkoutLatitude,
      checkoutLongitude,
      suggested_voucher_id,
    } = data;

    const { note, po_attachment } = req.files;

    const attachmentFileName =
      note && Array.isArray(note) && note[0].filename ? note[0].filename : null;

    const poAttachmentFileName =
      po_attachment && Array.isArray(po_attachment) && po_attachment[0].filename
        ? po_attachment[0].filename
        : null;

    const serviceResponse = await checkoutService(
      customerId,
      {
        shipping_type,
        payment_method,
        buildcredit_payment: rpaf_payment,
        bank_payment,
        voucher_code,
        pickup_date,
        order_instructions,
        agent_code,
        transportify_shipping_fee,
        lalamove_shipping_fee,
        lalamove_quotation_id,
        lalamove_customer_stop_id,
        lalamove_seller_stop_id,
        checkoutAddress,
        checkoutLatitude,
        checkoutLongitude,
        bank_transfer_attachment: attachmentFileName,
        suggested_voucher_id,
        poAttachmentFileName,
      },
      req
    );

    if (serviceResponse.error) {
      const itemStockError = serviceResponse.itemStockError || false;

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

exports.mockCheckout = async (req, res, next) => {
  try {
    const { customerId } = req;
    const {
      shipping_type,
      payment_method,
      rpaf_payment,
      bank_payment,
      voucher_code,
      pickup_date,
      order_instructions,
      agent_code,
      transportify_shipping_fee,
      lalamove_shipping_fee,
      checkoutAddress,
      checkoutLatitude,
      checkoutLongitude,
      suggested_voucher_id,
    } = req.body;

    const serviceResponse = await mockCheckoutServicev2(
      customerId,
      {
        shipping_type,
        payment_method,
        buildcredit_payment: rpaf_payment,
        bank_payment,
        voucher_code,
        pickup_date,
        order_instructions,
        agent_code,
        transportify_shipping_fee,
        lalamove_shipping_fee,
        checkoutAddress,
        checkoutLatitude,
        checkoutLongitude,
        suggested_voucher_id,
      },
      req
    );

    if (serviceResponse.error) {

      const itemStockError = serviceResponse.itemStockError || false;
      return res
        .status(200)
        .json({ success: false, response: serviceResponse.error, itemStockError });
    }
    res.status(200).json({ success: true, response: serviceResponse });
  } catch (err) {
    next(err);
  }
};

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

    const checkoutFallback = await checkoutPaymentFallbackService(
      customerId,
      reference_no
    );

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

exports.generateQr = async (req, res, next) => {
  try {
    const { reference_no } = req.query;

    if (!reference_no) {
      return res.status(400).json({ error: "reference_no is required" });
    }

    const orderForm = await OrderForm.findOne({
      where: {
        reference_no,
      },
    });
    if (!orderForm) {
      return res.status(400).json({ error: "Invalid reference no" });
    }

    const qrCodeFilePath = path.join(__dirname, `${reference_no}.png`);
    await QRCode.toFile(qrCodeFilePath, reference_no);

    res.setHeader(
      "Content-Disposition",
      `attachment; filename="${reference_no}.png"`
    );
    res.setHeader("Content-Type", "image/png");

    res.sendFile(qrCodeFilePath, (err) => {
      if (err) {
        next(err);
      } else {
        fs.unlinkSync(qrCodeFilePath);
      }
    });
  } catch (error) {
    next(error);
  }
};

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

    const customerInfo = await Customers.findByPk(customerId);
    const paymentMethods = await availablePaymentMethodService(
      req,
      customerId,
      { yieldCode: customerInfo?.yield_code }
    );

    if (paymentMethods.error) {
      return res
        .status(200)
        .json({ success: false, response: paymentMethods.error });
    }

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

exports.paymentMethodWebhook = async (req, res, next) => {
  try {
    const { id, type, data, creation_time } = req.body;

    const webHook = await WebhookCatch.create({
      response_data: JSON.stringify({
        id,
        type,
        data,
        creation_time,
      }),
      from_api: "Yield",
      webhook_timestamp: new Date(),
      type: "Payment",
    });

    if (data && data.order_id && data.order_id !== "" && type && type !== "") {
      const orderId = data.order_id;

      const yieldOrder = await req.yieldClient.fetchOrder(orderId);

      if (yieldOrder && yieldOrder.id && yieldOrder.status) {
        const { id } = yieldOrder;

        const customerOrder = await OrderForm.findOne({
          where: {
            third_party_payment_id: id,
          },
        });

        if (!customerOrder)
          return res
            .status(400)
            .json({ success: false, message: "Order not found." });

        switch (yieldOrder.status) {
          case "PENDING":
            customerOrder.status = "To Pay";
            break;
          case "CONFIRMED":
            customerOrder.dateTime_verified = new Date();
            customerOrder.status = "Verified";
            break;
          case "FULFILLED":
            break;
          case "CANCELLED":
            customerOrder.status = "Cancelled";
            break;
          default:
            return res
              .status(400)
              .json({ success: false, message: "Status not recognized." });
        }

        await customerOrder.save();
        return res
          .status(200)
          .json({ success: true, message: "Webhook processed successfully." });
      }
    }

    return res
      .status(400)
      .json({ success: false, message: "Invalid webhook payload." });
  } catch (err) {
    next(err);
  }
};
