//If this value is false then the payment form will be shown inside iframe directly inside the widget
//If this value is true then a customer will be redirected to payment page with order status checking via js
const redirect = false;
const path = require("path");
const crypto = require("crypto");
const axios = require("axios");
const fastify = require("fastify")({
  logger: false,
});

fastify.register(require("@fastify/static"), {
  root: path.join(__dirname, "public"),
  prefix: "/", // optional: default '/'
});

fastify.register(require("@fastify/view"), {
  engine: {
    handlebars: require("handlebars"),
  },
});

//Generates hash for Bukza: hash = base64(hmacSha256(userId + orderNumber + command + data + amount + timestamp), bukza_key)
function generateBukzaHash(payload) {
  const hmac = crypto.createHmac("sha256", process.env.bukza_key);
  hmac.update(
    payload.userId +
      payload.orderNumber +
      payload.command +
      payload.data +
      payload.amount +
      payload.timestamp
  );
  const sha256 = hmac.digest("hex");
  const base64 = Buffer.from(sha256, "hex").toString("base64");
  return base64;
}

//Handler for requests from Bukza
fastify.post("/bukzaHandler", async (request, reply) => {
  try {
    const body = request.body;
    console.log(`Received ${body.command} request from Bukza:`);
    console.log(body);

    if (generateBukzaHash(body) != body.hash) {
      reply.code(400).send({ error: "Invalid hash." });
      return;
    }

    switch (body.command) {
      case "GetPaymentData": {
        const data = {
          url: `https://${process.env.PROJECT_DOMAIN}.glitch.me/?userId=${body.userId}&orderNumber=${body.orderNumber}&amount=${body.amount}&checkStateToken=${encodeURIComponent(body.checkStateToken)}&culture=${body.culture}`,
          redirect: redirect
        };
        console.log("Responded to Bukza:");
        console.log(data);
        reply.code(200).send(data);
        break;
      }
      case "Cancel": {
        //TODO Send request to PaymentGateway
        reply.code(200).send(null);
        break;
      }
      case "Capture": {
        //TODO Send request to PaymentGateway
        reply.code(200).send(null);
        break;
      }
      case "Refund": {
        //TODO Send request to PaymentGateway
        reply.code(200).send(null);
        break;
      }
      default: {
        reply.code(400).send({ error: "Unknown command." });
      }
    }
  } catch (error) {
    console.error(error);
    reply.code(500).send({ error: "Server error" });
  }
});

//Renders the page with the "Pay" button from /index.hbs
fastify.get("/", function (request, reply) {
  let params = {
    url: `https://${process.env.PROJECT_DOMAIN}.glitch.me`,
    userId: request.query.userId,
    orderNumber: request.query.orderNumber,
    amount: request.query.amount,
    redirect: redirect
  };
  return reply.view("/index.hbs", params);
});

//"Pay" button handler
fastify.post("/pay", async (request, reply) => {
  const body = request.body;

  //TODO Send the payment request to your PaymentGateway. It should respond to /paymentGatewayHandler

  //TODO: Remove the code below, as it imitates the response from your Payment Gateway
  axios
    .post(
      `https://${process.env.PROJECT_DOMAIN}.glitch.me/paymentGatewayHandler`,
      request.body
    )
    .then((response) => {
      console.log("Success:", response.data);
      reply.code(200).send(response.data);
    })
    .catch((error) => {
      console.error("Error:", error);
      reply.code(400).send(error);
    });
});

//Handler for requests form your Payment Gateway
fastify.post("/paymentGatewayHandler", async (request, reply) => {
  try {
    const body = request.body;
    console.log("Received response from Payment Gateway:");
    console.log(body);

    const timestamp = Math.floor(new Date().getTime() / 1000.0);

    //If we set bukza_user_id in .env then use it
    const userId = process.env.bukza_user_id
      ? process.env.bukza_user_id
      : request.body.userId;

    const payload = {
      userId: userId,
      orderNumber: request.body.orderNumber,
      command: "AuthorizeCallback", //Or use "CaptureCallback" for simplified mode
      data: request.body.orderNumber + "_" + timestamp, //Replace it with PaymentGateway internal transaction id
      amount: request.body.amount,
      timestamp: timestamp,
      hash: null,
      comment: "Operation " + request.body.orderNumber + "_" + timestamp, //Replace it with PaymentGateway internal transaction id
    };

    payload.hash = generateBukzaHash(payload);

    console.log("Sending request to Bukza:");
    console.log(payload);

    axios
      .post("https://public.bukza.com/api/pay", payload)
      .then((response) => {
        console.log("Success:", response.data);
        reply.code(200).send(response.data);
      })
      .catch((error) => {
        console.error("Error:", error);
        reply.code(400).send(error);
      });
  } catch (error) {
    console.error(error);
    reply.code(500).send({ error: "Server error" });
  }
});

fastify.listen(
  { port: process.env.PORT, host: "0.0.0.0" },
  function (err, address) {
    if (err) {
      console.error(err);
      process.exit(1);
    }
    console.log(`Your app is listening on ${address}`);
  }
);
