/**
 * A2P AutoPilot - Main Entry Point
 * Sets up Express server, database, Redis, and BullMQ workers
 */

import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import dotenv from 'dotenv';
import { initializeDatabase, closeDatabase } from './db/index';
import { runMigrations } from './db/migrate';
import { logger } from './utils/logger';
import routes from './api/routes';
import {
  requestLogger,
  errorHandler,
  notFoundHandler,
} from './api/middleware';

// Load environment variables
dotenv.config();

// ============================================================
// CONFIGURATION
// ============================================================

const PORT = process.env.PORT || 3000;
const DATABASE_URL = process.env.DATABASE_URL;
const REDIS_URL = process.env.REDIS_URL;
const NODE_ENV = process.env.NODE_ENV || 'development';

// Validate required environment variables
const requiredEnvVars = ['DATABASE_URL', 'REDIS_URL', 'API_KEY', 'TWILIO_ACCOUNT_SID', 'TWILIO_AUTH_TOKEN'];
const missing = requiredEnvVars.filter((key) => !process.env[key]);

if (missing.length > 0) {
  logger.error({ missing }, 'Missing required environment variables');
  process.exit(1);
}

// ============================================================
// EXPRESS APP SETUP
// ============================================================

const app = express();

// Security middleware
app.use(helmet());

// CORS configuration
app.use(
  cors({
    origin: process.env.CORS_ORIGIN || '*',
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
    allowedHeaders: ['Content-Type', 'Authorization'],
  })
);

// Body parsing
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));

// Request logging
app.use(requestLogger);

// Mount API routes
app.use('/api', routes);

// Health check at root
app.get('/', (_req, res) => {
  res.json({
    service: 'a2p-autopilot',
    version: '1.0.0',
    status: 'running',
    environment: NODE_ENV,
  });
});

// 404 handler
app.use(notFoundHandler);

// Global error handler (must be last)
app.use(errorHandler);

// ============================================================
// DATABASE & REDIS INITIALIZATION
// ============================================================

async function initializeServices() {
  logger.info('Initializing services...');

  // 1. Connect to PostgreSQL
  try {
    initializeDatabase(DATABASE_URL!);
    logger.info('✓ Database connected');
  } catch (error) {
    logger.error({ error }, 'Failed to connect to database');
    throw error;
  }

  // 2. Run migrations
  try {
    await runMigrations(DATABASE_URL!);
    logger.info('✓ Database migrations completed');
  } catch (error) {
    logger.error({ error }, 'Failed to run migrations');
    throw error;
  }

  // 3. Connect to Redis
  // TODO: Initialize Redis client
  logger.info('✓ Redis connected (TODO)');

  // 4. Initialize BullMQ workers
  // TODO: Start BullMQ workers for polling and submission processing
  logger.info('✓ BullMQ workers started (TODO)');
}

// ============================================================
// SERVER STARTUP
// ============================================================

async function startServer() {
  try {
    await initializeServices();

    const server = app.listen(PORT, () => {
      logger.info(
        {
          port: PORT,
          env: NODE_ENV,
          processId: process.pid,
        },
        `🚀 A2P AutoPilot server running on port ${PORT}`
      );
    });

    // Graceful shutdown handling
    const shutdown = async (signal: string) => {
      logger.info({ signal }, 'Shutdown signal received');

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

        try {
          // Close database connection
          await closeDatabase();
          logger.info('Database connection closed');

          // TODO: Close Redis connection
          // await closeRedis();

          // TODO: Close BullMQ workers
          // await closeBullMQ();

          logger.info('Graceful shutdown complete');
          process.exit(0);
        } catch (error) {
          logger.error({ error }, 'Error during shutdown');
          process.exit(1);
        }
      });

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

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

    // Handle uncaught errors
    process.on('uncaughtException', (error) => {
      logger.error({ error }, 'Uncaught exception');
      shutdown('uncaughtException');
    });

    process.on('unhandledRejection', (reason, promise) => {
      logger.error({ reason, promise }, 'Unhandled promise rejection');
      shutdown('unhandledRejection');
    });
  } catch (error) {
    logger.error({ error }, 'Failed to start server');
    process.exit(1);
  }
}

// Start the server
startServer();
