import http from 'http';
import net from 'net';
import dotenv from 'dotenv';
import path from 'path';

// Load environment variables from .env file FIRST
dotenv.config({ path: path.resolve(__dirname, '../.env') });
// Stop queue metrics collection on shutdown
// Note: This is imported statically but doesn't trigger database/queue activity until called
import { stopQueueMetrics } from './utils/queueMetrics';

const PORT: number = parseInt(process.env.PORT || '5000', 10);
const isDev = process.env.NODE_ENV !== 'production';
const MAX_PORT_ATTEMPTS = isDev ? 6 : 1; // In dev try PORT..PORT+5 if in use

/**
 * Check if a port is free (no one listening).
 */
function isPortFree(port: number): Promise<boolean> {
  return new Promise((resolve) => {
    const socket = new net.Socket();
    const onError = () => {
      socket.destroy();
      resolve(true); // Error (e.g. ECONNREFUSED) means nothing listening → port free
    };
    socket.setTimeout(200);
    socket.once('error', onError);
    socket.once('timeout', () => {
      socket.destroy();
      resolve(true);
    });
    socket.connect(port, '127.0.0.1', () => {
      socket.destroy();
      resolve(false); // Connected → something is listening → port in use
    });
  });
}

/**
 * Find first free port in [startPort, startPort + maxAttempts).
 */
async function findFreePort(startPort: number, maxAttempts: number): Promise<number> {
  for (let i = 0; i < maxAttempts; i++) {
    const port = startPort + i;
    if (await isPortFree(port)) return port;
  }
  return startPort; // Fallback to original; listen will then fail with EADDRINUSE
}

// Start server
const startServer = async (): Promise<void> => {
  try {
    // Initialize Google Secret Manager before starting server
    // This will merge secrets from GCS into process.env if enabled
    const { initializeGoogleSecretManager } = require('./services/googleSecretManager.service');
    console.log('🔐 Initializing secrets...');
    await initializeGoogleSecretManager();

    const { default: app, initializeAppDatabase } = require('./app');
    const { initSocket } = require('./realtime/socket');

    // Initialize database connection explicitly after secrets are loaded
    await initializeAppDatabase();

    // Apply pending DB migrations automatically in non-production to prevent schema drift.
    // Can be disabled via RUN_MIGRATIONS_ON_STARTUP=false
    const autoMigrate =
      process.env.RUN_MIGRATIONS_ON_STARTUP === 'true' ||
      process.env.NODE_ENV !== 'production';
    if (autoMigrate) {
      try {
        const { runMigrations } = require('./scripts/migrate');
        await runMigrations();
      } catch (e) {
        console.error('❌ Auto migration on startup failed:', e);
        process.exit(1);
      }
    }

    require('./queues/tatWorker'); // Initialize TAT worker
    const { logTatConfig } = require('./config/tat.config');
    const { logSystemConfig } = require('./config/system.config');
    const { initializeHolidaysCache } = require('./utils/tatTimeUtils');
    const { seedDefaultConfigurations } = require('./services/configSeed.service');
    const { startPauseResumeJob } = require('./jobs/pauseResumeJob');
    require('./queues/pauseResumeWorker'); // Initialize pause resume worker
    const { initializeQueueMetrics } = require('./utils/queueMetrics');
    const { emailService } = require('./services/email.service');

    // Initialize email service after secrets are loaded
    try {
      await emailService.initialize();
      console.log('📧 Email service initialized');
    } catch (error) {
      console.warn('⚠️  Email service initialization warning (will use test account if SMTP not configured):', error);
    }

    const server = http.createServer(app);
    initSocket(server);

    // Seed default configurations if table is empty
    try {
      await seedDefaultConfigurations();
    } catch (error) {
      console.error('⚠️  Configuration seeding error:', error);
    }

    // Seed default activity types if table is empty
    const { seedDefaultActivityTypes } = require('./services/activityTypeSeed.service');
    try {
      await seedDefaultActivityTypes();
    } catch (error) {
      console.error('⚠️  Activity type seeding error:', error);
    }

  
    // Initialize holidays cache for TAT calculations
    try {
      await initializeHolidaysCache();
    } catch (error) {
      // Silently fall back to weekends-only TAT calculation
    }

    // Start scheduled jobs
    startPauseResumeJob();
    const { startForm16NotificationJobs } = require('./jobs/form16NotificationJob');
    startForm16NotificationJobs();
    const { startForm16ArchiveJob } = require('./services/form16Archive.service');
    startForm16ArchiveJob();
    const { startCreditNoteSyncJob } = require('./jobs/creditNoteSyncJob');
    startCreditNoteSyncJob();

    // Initialize queue metrics collection for Prometheus
    initializeQueueMetrics();

    // In development, if default port is in use (e.g. previous run or another app), try next ports
    let portToUse = PORT;
    if (isDev) {
      const freePort = await findFreePort(PORT, MAX_PORT_ATTEMPTS);
      if (freePort !== PORT) {
        console.warn(`⚠️  Port ${PORT} is in use. Using port ${freePort} instead.`);
        console.warn(`   Update frontend .env VITE_API_BASE_URL to http://localhost:${freePort}/api/v1 if needed.`);
        portToUse = freePort;
      }
    }

    server.once('error', (err: NodeJS.ErrnoException) => {
      if (err.code === 'EADDRINUSE') {
        console.error('');
        console.error('❌ Port ' + portToUse + ' is already in use.');
        console.error('   Another process (often a previous backend instance) is using it.');
        console.error('   Windows: netstat -ano | findstr :' + portToUse);
        console.error('   Then: taskkill /PID <PID> /F');
        console.error('   Or run in a single terminal and avoid starting backend twice.');
        console.error('');
      } else {
        console.error('❌ Server error:', err);
      }
      process.exit(1);
    });

    server.listen(portToUse, () => {
      console.log(`🚀 Server running on port ${portToUse} | ${process.env.NODE_ENV || 'development'}`);
      console.log(`   API base: http://localhost:${portToUse}/api/v1 (ensure frontend uses this and CORS allows your origin)`);
    });
  } catch (error) {
    console.error('❌ Unable to start server:', error);
    process.exit(1);
  }
};

// Graceful shutdown
process.on('SIGTERM', () => {
  console.log('🛑 SIGTERM signal received: closing HTTP server');
  stopQueueMetrics();
  process.exit(0);
});

process.on('SIGINT', () => {
  console.log('🛑 SIGINT signal received: closing HTTP server');
  stopQueueMetrics();
  process.exit(0);
});

startServer();