import { loadConfig } from './config.ts';
import { createApp, type AppConfig } from './app.ts';
import { openDatabase } from './db/connection.ts';
import { runMigrations } from './db/migrate.ts';
import { deleteOldItems } from './db/repos/items.ts';
import { createPoller } from './poller/scheduler.ts';
import type { Poller } from './poller/scheduler.ts';
import { bus } from './events.ts';
import { createLogger } from './logger.ts';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import type { DatabaseSync } from 'node:sqlite';
import type { Server } from 'node:http';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const migrationsDir = path.resolve(__dirname, 'db', 'migrations');

type Config = ReturnType<typeof loadConfig>;

const config: Config = loadConfig();
const logger = createLogger(config.LOG_LEVEL);
const db: DatabaseSync = openDatabase(config.DATABASE_PATH);
runMigrations(db, migrationsDir);

const poller: Poller = createPoller(db, bus);
const app = createApp({ config: config as AppConfig, db });
const server: Server = app.listen(config.PORT, () => {
  logger.info({ port: config.PORT }, 'truf listening');
});
poller.start();

const RETENTION_DAYS = 90;
function runRetention(): void {
  const cutoff = new Date(Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1000).toISOString();
  deleteOldItems(db, cutoff);
  logger.info({ cutoff }, 'retention cleanup');
}
runRetention();
const retentionHandle: NodeJS.Timeout = setInterval(runRetention, 24 * 60 * 60 * 1000);

let shuttingDown = false;

function shutdown(signal: NodeJS.Signals): void {
  if (shuttingDown) {
    process.exit(1);
  }
  shuttingDown = true;
  logger.info({ signal }, 'shutting down');

  const forceExit = setTimeout(() => process.exit(1), 5000);
  forceExit.unref();

  poller.stop();
  clearInterval(retentionHandle);

  try {
    server.closeIdleConnections?.();
    server.closeAllConnections?.();
  } catch {
    // ignore
  }

  server.close(() => {
    try {
      db.close();
    } catch {
      /* ignore */
    }
    clearTimeout(forceExit);
    process.exit(0);
  });
}

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