const OrderForm = require("../../models/OrderForm");
const PaynamicsTransactions = require("../../models/PaynamicsTransactions");

const TRANSACTION_SUCCESS = "GR001";
const TRANSACTION_SUCCESS_3DS = "GR002";
const TRANSACTION_FAILED = "GR003";
const TRANSACTION_PENDING = "GR033";
const TRANSACTION_CANCELLED = "GR053";
const TRANSACTION_EXPIRED = "GR152";
const TRANSACTION_TIMEOUT = "GR092";

const API_REMARKS_INVALID_ORDER_REF = "Invalid Order Reference Number.";
const API_REMARKS_ORDER_REF_NOT_FOUND = "Order Reference Number not found.";

const ORDER_VERIFIED = "Verified";
const ORDER_FAILED = "PAYMENT FAILED";
const ORDER_CANCELLED = "Cancelled";
const ORDER_PENDING = "Pending";
const ORDER_EXPIRED = "Payment Expired";
const ORDER_TIMEOUT = "Payment Timeout";

const logToTransaction = async ({
  order_reference_no,
  response_code,
  response_advise,
  response_message,
  signature,
  response_id,
  merchant_id,
  request_id,
  payment_action_info,
  timestamp,
  payment_success,
  api_remarks,
}) => {
  try {
    return PaynamicsTransactions.create({
      order_reference_no,
      response_code,
      response_advise,
      response_message,
      signature,
      response_id,
      merchant_id,
      request_id,
      payment_action_info,
      timestamp,
      payment_success,
      api_remarks,
    });
  } catch (err) {
    throw err;
  }
};

exports.verifyAndCompletePayment = async (req, res, next) => {
  const {
    response_code,
    response_advise,
    response_message,
    signature,
    response_id,
    merchant_id,
    expiry_limit,
    request_id,
    payment_action_info,
    timestamp,
  } = req.body;

  try {
    let order_reference_no = "";
    if (request_id) order_reference_no = request_id.split("-").slice(1).join("-");
    
    const transactionJson = {
      order_reference_no,
      response_code,
      response_advise,
      response_message,
      signature,
      response_id,
      merchant_id,
      request_id,
      payment_action_info,
      timestamp,
      payment_success: false,
      api_remarks: "",
    };

    if (!order_reference_no || order_reference_no === "") {
      transactionJson.api_remarks = API_REMARKS_INVALID_ORDER_REF;
      await logToTransaction(transactionJson);
      return res.status(401).json({ success: false, message: API_REMARKS_INVALID_ORDER_REF });
    }

    const orderForm = await OrderForm.findOne({
      where: {
        reference_no: order_reference_no,
      },
    });

    if (!orderForm) {
      transactionJson.api_remarks = API_REMARKS_ORDER_REF_NOT_FOUND;
      await logToTransaction(transactionJson);
      return res.status(401).json({ success: false, message: API_REMARKS_ORDER_REF_NOT_FOUND });
    }

    const promises = [];
    let orderStatus = ORDER_PENDING;

    switch (response_code) {
      case TRANSACTION_SUCCESS:
        orderStatus = ORDER_VERIFIED;
        transactionJson.api_remarks = "Payment Success";
        break;
      case TRANSACTION_SUCCESS_3DS:
        orderStatus = ORDER_VERIFIED;
        transactionJson.api_remarks = "Payment Success 3DS";
        break;
      case TRANSACTION_FAILED:
        orderStatus = ORDER_FAILED;
        transactionJson.api_remarks = "Payment Failed";
        break;
      case TRANSACTION_PENDING:
        orderStatus = ORDER_PENDING;
        transactionJson.api_remarks = "Payment Pending";
        break;
      case TRANSACTION_CANCELLED:
        orderStatus = ORDER_CANCELLED;
        transactionJson.api_remarks = "Payment Cancelled";
        break;
      case TRANSACTION_EXPIRED:
        orderStatus = ORDER_EXPIRED;
        transactionJson.api_remarks = "Payment Expired";
        break;
      case TRANSACTION_TIMEOUT:
        orderStatus = ORDER_TIMEOUT;
        transactionJson.api_remarks = "Payment Timeout";
        break;
      default:
        orderStatus = ORDER_PENDING;
        transactionJson.api_remarks = "Payment Pending";
        break;
    }

    orderForm.status = orderStatus;
    promises.push(orderForm.save());
    promises.push(logToTransaction(transactionJson));

    await Promise.all(promises);

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