import { createApp } from "./app";
import { prisma } from "./db";
import { appUrl, nodeEnv, port } from "./env";
import { ipayCheckoutUrl, ipayConfigured } from "./ipay";
import { loadProducts } from "./products";

const app = createApp();
const server = app.listen(port(), "0.0.0.0", () => {
  const products = loadProducts();
  console.log(`Optimize Solutions payment hub listening on :${port()}`);
  console.log(`Public URL ${appUrl()}`);
  console.log(`iPay checkout ${ipayCheckoutUrl()}`);
  console.log(`Products: ${products.map((product) => product.id).join(", ")}`);
  if (!ipayConfigured()) {
    console.warn("iPay token or secret is empty. POST /api/v1/checkout will return 503 until both are set.");
  }
  if (nodeEnv() === "production" && ipayCheckoutUrl().includes("sandbox.ipay.lk")) {
    console.warn("NODE_ENV is production but the iPay checkout URL is still the sandbox.");
  }
  setTimeout(() => {
    void fetch(`http://127.0.0.1:${port()}/health`)
      .then(async (res) => {
        const body = await res.text();
        if (!body.includes('"status":"ok"')) {
          console.warn(
            `Another program is answering http://127.0.0.1:${port()}. Stop it, or this hub will not be what opens at localhost:${port()}.`
          );
        }
      })
      .catch(() => {
        console.warn(`Could not confirm http://127.0.0.1:${port()}/health is this hub.`);
      });
  }, 300).unref();
});

server.on("error", (err: NodeJS.ErrnoException) => {
  if (err.code === "EADDRINUSE") {
    console.error(`Port ${port()} is already in use. Stop the other process or change PORT.`);
  } else {
    console.error(err);
  }
  process.exit(1);
});

function shutdown(signal: string): void {
  console.log(`Received ${signal}, shutting down`);
  server.close(() => {
    void prisma.$disconnect().finally(() => process.exit(0));
  });
  setTimeout(() => process.exit(1), 10_000).unref();
}

process.on("SIGINT", () => shutdown("SIGINT"));
process.on("SIGTERM", () => shutdown("SIGTERM"));
