import app from "./app.js";
import dotenv from "dotenv";
import db from "./models/index.js";
import { checkInactivity, syncExchangeRates, syncPendingKybApplications, syncMerchantWalletCurrencies } from "./services/cronService.js";

dotenv.config();

const PORT = process.env.PORT || 8000;

// Payout reconciliation is intentionally NOT scheduled here. This file runs in PM2 cluster
// mode with multiple instances in production — a setInterval in this file would run once per
// cluster worker, all in parallel, all racing to resolve the same pending payouts at once.
// It runs instead as its own dedicated single-instance PM2 app: see
// src/scripts/payoutReconciliationWorker.js and the "payout-reconciliation-worker" entry in
// ecosystem.config.cjs.

const server = app.listen(PORT, () => {
  console.log(`🚀 SaaS Server running on http://localhost:${PORT}`);
  
  // Schedule inactivity check every 6 hours
  setInterval(checkInactivity, 6 * 60 * 60 * 1000);
  // Run once on startup after 10 seconds
  setTimeout(checkInactivity, 10000);

  // Schedule exchange rate sync every 1 hour
  setInterval(syncExchangeRates, 1 * 60 * 60 * 1000);
  // Run once on startup after 15 seconds
  setTimeout(syncExchangeRates, 15000);

  // Schedule pending KYB sync (fallback for missed/failed Didit webhooks) every 30 minutes
  setInterval(syncPendingKybApplications, 30 * 60 * 1000);
  // Run once on startup after 20 seconds
  setTimeout(syncPendingKybApplications, 20000);

  // Schedule merchant wallet/currency sync once every 24 hours
  setInterval(syncMerchantWalletCurrencies, 24 * 60 * 60 * 1000);
  // Run once on startup after 25 seconds, so the checks the user asked for happen before anything else settles
  setTimeout(syncMerchantWalletCurrencies, 25000);
});

/**
 * Graceful Shutdown Handler
 */
const shutdown = async (signal) => {
    console.log(`\nRECEIVED ${signal} - Closing server gracefully...`);
    
    server.close(async () => {
        console.log("✔ HTTP Server closed.");
        
        try {
            await db.sequelize.close();
            console.log("✔ Database connections closed.");
            process.exit(0);
        } catch (error) {
            console.error("❌ Error closing DB connections:", error.message);
            process.exit(1);
        }
    });

    // Forced exit if it takes too long (10s)
    setTimeout(() => {
        console.error("❌ Forced shutdown due to timeout.");
        process.exit(1);
    }, 10000);
};

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

// Unhandled Promise Rejections
// Logged, not fatal: a single stray rejection anywhere in the app (e.g. a missed .catch()
// on a background email/webhook call) should not kill this whole worker and drop every
// other in-flight request it's currently serving. This is a visibility net, not a crash
// trigger — genuine request-handling errors are already caught by Express's own error
// middleware in app.js and returned as a normal error response.
process.on("unhandledRejection", (err) => {
    console.error("🌑 UNHANDLED REJECTION (logged, process continues):", err?.stack || err);
});
