import app from './app';
import environment from './config/environment';
import logger from './utils/logger';
import { testConnection, closePool, runMigrations } from './config/database';
import { startAuditCleanupJob, stopAuditCleanupJob } from './jobs/audit-cleanup.job';
import { startNotificationJob, stopNotificationJob } from './jobs/notification-generation.job';
import { startReminderJob, stopReminderJob } from './jobs/reminder.job';
import { startIssueReminderJob, stopIssueReminderJob } from './jobs/issue-reminder.job';
import { startChecklistReminderJob, stopChecklistReminderJob } from './jobs/checklist-reminder.job';
import { startBuchhaltungRecurringJob, stopBuchhaltungRecurringJob } from './jobs/buchhaltung-recurring.job';
import { startScheduledMessagesJob, stopScheduledMessagesJob } from './jobs/scheduled-messages.job';
import { permissionService } from './services/permission.service';

const startServer = async (): Promise<void> => {
  try {
    // Test database connection
    logger.info('Testing database connection...');
    const dbConnected = await testConnection();

    if (!dbConnected) {
      logger.warn('Database connection failed - server will start but database operations may fail');
    } else {
      // Run pending migrations automatically on startup
      await runMigrations();

      // Load permission cache after migrations
      await permissionService.loadCache();
    }

    // Start the GDPR IP anonymisation job
    startAuditCleanupJob();

    // Start the notification generation job
    startNotificationJob();

    // Start the order reminder job
    startReminderJob();

    // Start the issue reminder job
    startIssueReminderJob();

    // Start the checklist reminder job
    startChecklistReminderJob();

    // Start the buchhaltung recurring transaction job
    startBuchhaltungRecurringJob();

    // Start the scheduled messages job
    startScheduledMessagesJob();

    // Start the server
    const server = app.listen(environment.port, () => {
      logger.info('Server started successfully', {
        port:        environment.port,
        environment: environment.nodeEnv,
        database:    dbConnected ? 'connected' : 'disconnected',
      });

      // Log integration status so operators can see what's configured
      logger.info('Integration status', {
        bookstack:  !!environment.bookstack.url,
        nextcloud:  !!environment.nextcloudUrl,
        vikunja:    !!environment.vikunja.url,
      });
    });

    // Graceful shutdown handling
    const gracefulShutdown = async (signal: string) => {
      logger.info(`${signal} received. Starting graceful shutdown...`);

      // Stop scheduled jobs first
      stopAuditCleanupJob();
      stopNotificationJob();
      stopReminderJob();
      stopIssueReminderJob();
      stopChecklistReminderJob();
      stopBuchhaltungRecurringJob();
      stopScheduledMessagesJob();

      server.close(async () => {
        logger.info('HTTP server closed');

        // Close database connection
        await closePool();

        logger.info('Graceful shutdown completed');
        process.exit(0);
      });

      // Force shutdown after 10 seconds
      setTimeout(() => {
        logger.error('Forced shutdown after timeout');
        process.exit(1);
      }, 10000);
    };

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

  } catch (error) {
    logger.error('Failed to start server', { error });
    process.exit(1);
  }
};

// Handle unhandled promise rejections
process.on('unhandledRejection', (reason: Error, _promise: Promise<any>) => {
  logger.error('Unhandled Promise Rejection', {
    reason: reason.message,
    stack: reason.stack,
  });
});

// Handle uncaught exceptions
process.on('uncaughtException', (error: Error) => {
  logger.error('Uncaught Exception', {
    message: error.message,
    stack: error.stack,
  });
  process.exit(1);
});

// Start the server
startServer();
