import { env } from './config/env.js';
import { db } from './db/client.js';
import { createApp } from './app.js';
import { ChatService } from './services/chat-service.js';
import { ensureChatConversationTables } from './services/chat-room-service.js';
import { shutdownNotificationProvider } from './services/notification-service.js';
import { ServerRestartReservationWorker } from './services/server-restart-reservation-service.js';
import { BaseballTicketBayWorker } from './workers/baseball-ticket-bay-worker.js';
import { PlanWorker } from './workers/plan-worker.js';

const app = createApp();
const planWorker = new PlanWorker(app.log);
const baseballTicketBayWorker = new BaseballTicketBayWorker(app.log);
const serverRestartReservationWorker = new ServerRestartReservationWorker(app.log);
const chatService = new ChatService(app.log);
const startedAt = Date.now();
let shutdownPromise: Promise<void> | null = null;
app.server.on('upgrade', chatService.attachUpgradeHandler());

async function start() {
  try {
    await ensureChatConversationTables();
    await chatService.recoverInterruptedSessions();
    await app.listen({
      host: '0.0.0.0',
      port: env.PORT,
    });
    planWorker.start();
    baseballTicketBayWorker.start();
    serverRestartReservationWorker.start();
  } catch (error) {
    app.log.error(error);
    process.exit(1);
  }
}

async function shutdown(signal: string) {
  if (shutdownPromise) {
    return shutdownPromise;
  }

  shutdownPromise = (async () => {
    app.log.warn({
      signal,
      pid: process.pid,
      uptimeSeconds: Math.round((Date.now() - startedAt) / 1000),
      rssBytes: process.memoryUsage().rss,
    }, 'Received shutdown signal');

    try {
      await planWorker.stop();
      await baseballTicketBayWorker.stop();
      await serverRestartReservationWorker.stop();
      chatService.close();
      await app.close();
      await shutdownNotificationProvider();
      await db.destroy();
      process.exitCode = 0;
    } catch (error) {
      app.log.error({ error, signal }, 'Failed to shut down cleanly');
      process.exitCode = 1;
    }
  })();

  return shutdownPromise;
}

process.on('SIGINT', () => {
  void shutdown('SIGINT');
});

process.on('SIGTERM', () => {
  void shutdown('SIGTERM');
});

void start();
