/**
 * Maintenance cleanup for expired auth/rate-limit rows.
 * Schedule via cron — never expose as a public HTTP route.
 *
 *   npm run db:cleanup
 */
import { PrismaMariaDb } from '@prisma/adapter-mariadb';
import { PrismaClient } from '../src/generated/prisma/client';

function requireEnv(name: string) {
  const value = process.env[name];
  if (!value) throw new Error(`Missing ${name}`);
  return value;
}

async function main() {
  const url = new URL(requireEnv('DATABASE_URL'));
  const adapter = new PrismaMariaDb({
    host: url.hostname,
    port: Number(url.port || 3306),
    user: decodeURIComponent(url.username),
    password: decodeURIComponent(url.password),
    database: url.pathname.slice(1),
    connectionLimit: 2,
  });
  const prisma = new PrismaClient({ adapter });
  const now = new Date();
  const batch = 1000;

  let sessions = 0;
  for (;;) {
    const rows = await prisma.session.findMany({
      where: { expiresAt: { lt: now } },
      select: { tokenHash: true },
      take: batch,
    });
    if (!rows.length) break;
    await prisma.session.deleteMany({ where: { tokenHash: { in: rows.map(r => r.tokenHash) } } });
    sessions += rows.length;
    if (rows.length < batch) break;
  }

  let resets = 0;
  for (;;) {
    const rows = await prisma.passwordReset.findMany({
      where: { expiresAt: { lt: now } },
      select: { tokenHash: true },
      take: batch,
    });
    if (!rows.length) break;
    await prisma.passwordReset.deleteMany({ where: { tokenHash: { in: rows.map(r => r.tokenHash) } } });
    resets += rows.length;
    if (rows.length < batch) break;
  }

  let buckets = 0;
  for (;;) {
    const rows = await prisma.rateLimitBucket.findMany({
      where: { expiresAt: { lt: now } },
      select: { key: true },
      take: batch,
    });
    if (!rows.length) break;
    await prisma.rateLimitBucket.deleteMany({ where: { key: { in: rows.map(r => r.key) } } });
    buckets += rows.length;
    if (rows.length < batch) break;
  }

  await prisma.$disconnect();
  process.stdout.write(`${JSON.stringify({ event: 'cleanup.expired', sessions, resets, buckets, at: now.toISOString() })}\n`);
}

main().catch(error => {
  process.stderr.write(`${JSON.stringify({ event: 'cleanup.failed', message: error instanceof Error ? error.message : 'unknown' })}\n`);
  process.exit(1);
});
