import pool from '../db';

const DEFAULT_EXPIRY_MINUTES = Number.parseInt(process.env.PENDING_ORDER_EXPIRY_MINUTES || '120', 10);
const DEFAULT_SLEEP_MS = 15 * 60 * 1000;

export async function expireStalePendingOrders(now: Date = new Date()): Promise<number> {
  const expiryMinutes = Number.isFinite(DEFAULT_EXPIRY_MINUTES) && DEFAULT_EXPIRY_MINUTES > 0
    ? DEFAULT_EXPIRY_MINUTES
    : 120;

  const { rows } = await pool.query(
    `WITH expired AS (
       UPDATE rm_pending_orders po
       SET status = 'expired'
       WHERE po.status = 'pending'
         AND po.created_at < $1::timestamptz - ($2 || ' minutes')::interval
         AND COALESCE(po.transaction_id, '') = ''
         AND po.completed_at IS NULL
         AND NOT EXISTS (
           SELECT 1
           FROM rm_purchases p
           WHERE p.stripe_session_id = po.invoice_number
         )
       RETURNING po.invoice_number
     )
     SELECT COUNT(*)::int AS count FROM expired`,
    [now.toISOString(), String(expiryMinutes)],
  );

  return Number(rows[0]?.count || 0);
}

let shuttingDown = false;
pool.on('error', (err) => {
  console.error('[pending-order-expiry] DB pool error:', err);
});

process.on('SIGTERM', () => { shuttingDown = true; });
process.on('SIGINT', () => { shuttingDown = true; });

async function main() {
  while (!shuttingDown) {
    try {
      const expired = await expireStalePendingOrders();
      console.log(`[pending-order-expiry] Expired ${expired} stale pending order(s)`);
    } catch (err: any) {
      console.error('[pending-order-expiry] Cycle error:', err?.message || err);
    }

    if (shuttingDown) break;
    await new Promise((resolve) => setTimeout(resolve, DEFAULT_SLEEP_MS));
  }

  await pool.end().catch(() => {});
}

if (process.env.VITEST !== 'true') {
  main().catch((err) => {
    console.error('[pending-order-expiry] Fatal error:', err);
    process.exit(1);
  });
}
