/**
 * DashCaddy API Server - Entry Point
 * Minimal startup script - all logic moved to src/
 */
const { createApp } = require('./src/app');
const { fetchT } = require('./src/utils/http');
const platformPaths = require('./platform-paths');

// Unhandled error handlers
process.on('unhandledRejection', (reason) => {
  console.error('[FATAL] Unhandled Promise Rejection:', reason);
  process.exit(1);
});

process.on('uncaughtException', (error) => {
  console.error('[FATAL] Uncaught Exception:', error);
  setTimeout(() => process.exit(1), 1000).unref();
});

// Main startup
(async () => {
  try {
    // Create and configure Express app
    const { app, log, config, licenseManager } = await createApp();
    
    // Load license
    await licenseManager.load();

    const PORT = parseInt(process.env.PORT, 10) || 3001;
    const HOST = process.env.HOST || '0.0.0.0';
    const CADDYFILE_PATH = process.env.CADDYFILE_PATH || platformPaths.caddyfile;
    const CADDY_ADMIN_URL = process.env.CADDY_ADMIN_URL || platformPaths.caddyAdminUrl;
    const SERVICES_FILE = process.env.SERVICES_FILE || platformPaths.servicesFile;
    const CONFIG_FILE = process.env.CONFIG_FILE || platformPaths.servicesFile.replace('services.json', 'config.json');

    // Validate startup configuration
    const { validateStartupConfig } = require('../src/utilities/startup-validator');
    await validateStartupConfig({
      log,
      CADDYFILE_PATH,
      SERVICES_FILE,
      CONFIG_FILE,
      CADDY_ADMIN_URL,
      PORT
    });

    // Start HTTP server
    const server = app.listen(PORT, HOST, () => {
      log.info('server', 'DashCaddy API server started', {
        port: PORT,
        host: HOST,
        caddyfile: CADDYFILE_PATH,
        caddyAdmin: CADDY_ADMIN_URL,
        services: SERVICES_FILE,
        environment: process.env.NODE_ENV || 'production'
      });

      // Attach WebSocket exec handler (with auth)
      const attachExecWS = require('./routes/exec');
      const authManager = require('../src/managers/auth-manager');
      attachExecWS(server, log, authManager);
      log.info('server', 'WebSocket exec handler attached (auth enforced)');

      // Start feature modules
      const resourceMonitor = require('../src/managers/resource-monitor');
      const backupManager = require('../src/utilities/backup-manager');
      const healthChecker = require('../src/monitoring/health-checker');
      const updateManager = require('../src/managers/update-manager');
      const selfUpdater = require('../src/docker/self-updater');
      const portLockManager = require('../src/managers/port-lock-manager');

      // Create servicesStateManager early — needed by workflow engine init
      const StateManager = require('./state-manager');
      const servicesStateManager = new StateManager(SERVICES_FILE);

      // Optional modules
      let dockerMaintenance, logDigest, bundledWorkflows;
      try { dockerMaintenance = require('../src/docker/docker-maintenance'); } catch { /* optional */ }
      try { logDigest = require('../src/security/log-digest'); } catch { /* optional */ }
      try { bundledWorkflows = require('../src/recipes/bundled-workflows'); } catch { /* optional */ }

      // Initialize workflow engine if bundled-workflows is available
      // NOTE: createApp() already initializes the workflow engine in src/app.js
      // This block is kept for backward compat with entry points that don't use createApp()
      let workflowEngine = null;
      if (bundledWorkflows) {
        try {
          const { fetchT } = require('./src/utils/http');
          const { WorkflowEngine } = bundledWorkflows;
          // Create a context with needed services
          const workflowCtx = {
            docker: { client: require('dockerode')() },
            notification: new (require('./src/managers/notification-manager'))({
              NOTIFICATIONS_FILE: process.env.NOTIFICATIONS_FILE || require('./platform-paths').notificationsFile,
              fetchT,
              log,
              config
            }),
            backupManager,
            resourceMonitor,
            servicesStateManager
          };
          workflowEngine = new WorkflowEngine(workflowCtx);
          log.info('server', 'Workflow engine initialized');
        } catch (err) {
          log.error('server', 'Workflow engine failed to initialize', { error: err.message });
        }
      }

      log.info('server', 'Starting feature modules');

      // Clean up stale port locks
      portLockManager.cleanupStaleLocks()
        .then(() => log.info('server', 'Port lock cleanup completed'))
        .catch(err => log.error('server', 'Port lock cleanup failed', { error: err.message }));

      // Resource monitoring
      try {
        resourceMonitor.start();
        // Connect workflow engine to resource monitor for resource-alert events
        if (workflowEngine) {
          resourceMonitor.setWorkflowEngine(workflowEngine);
        }
        log.info('server', 'Resource monitoring started');
      } catch (err) {
        log.error('server', 'Resource monitoring failed to start', { error: err.message });
      }

      // Backup manager
      try {
        backupManager.start();
        log.info('server', 'Backup manager started');
      } catch (err) {
        log.error('server', 'Backup manager failed to start', { error: err.message });
      }

      // Connect workflow engine to update manager for pre-update events
      if (workflowEngine) {
        updateManager.setWorkflowEngine(workflowEngine);
      }

      // Health checker (with service sync)
      (async () => {
        try {
          const { syncHealthCheckerServices } = require('../src/utilities/startup-validator');
          const StateManager = require('../src/managers/state-manager');
          const servicesStateManager = new StateManager(SERVICES_FILE);


          await syncHealthCheckerServices({
            log,
            SERVICES_FILE,
            servicesStateManager,
            healthChecker,
            buildServiceUrl: (subdomain) => config.routingMode === 'subdirectory' && config.domain
              ? `https://${config.domain}/${subdomain}`
              : `https://${subdomain}${config.tld}`,
            siteConfig: config,
            APP: require('../src/utilities/constants').APP
          });
          
          healthChecker.start();
          log.info('server', 'Health checker started');
        } catch (err) {
          log.error('server', 'Health checker failed to start', { error: err.message });
        }
      })();

      // Update manager
      try {
        updateManager.start();
        log.info('server', 'Update manager started');
      } catch (err) {
        log.error('server', 'Update manager failed to start', { error: err.message });
      }

      // Self-updater
      try {
        selfUpdater.start();
        log.info('server', 'Self-updater started', {
          interval: selfUpdater.config.checkInterval,
          url: selfUpdater.config.updateUrl
        });
        
        selfUpdater.checkPostUpdateResult()
          .then(result => {
            if (result) {
              log.info('server', 'Post-update result', result);
            }
          })
          .catch(() => {});
      } catch (err) {
        log.error('server', 'Self-updater failed to start', { error: err.message });
      }

      // Docker maintenance (optional)
      if (dockerMaintenance) {
        try {
          dockerMaintenance.start();
          log.info('server', 'Docker maintenance started');
          
          dockerMaintenance.on('maintenance-complete', (result) => {
            const saved = Math.round(result.spaceReclaimed.total / 1024 / 1024);
            if (saved > 0 || result.warnings.length > 0) {
              log.info('maintenance', 'Docker maintenance completed', {
                spaceReclaimedMB: saved,
                pruned: result.pruned,
                warnings: result.warnings.length
              });
            }
            if (result.warnings.length > 0) {
              for (const w of result.warnings) log.warn('maintenance', w);
            }
          });
        } catch (err) {
          log.error('server', 'Docker maintenance failed to start', { error: err.message });
        }
      }

      // Log digest (optional)
      if (logDigest) {
        try {
          logDigest.start(platformPaths.digestDir);
          log.info('server', 'Log digest started', { digestDir: platformPaths.digestDir });
          
          logDigest.on('digest-generated', ({ date }) => {
            log.info('digest', `Daily digest generated for ${date}`);
          });
        } catch (err) {
          log.error('server', 'Log digest failed to start', { error: err.message });
        }
      }

      log.info('server', 'All feature modules initialized');
    });

    // Graceful shutdown
    const shutdown = (signal) => {
      log.info('shutdown', `${signal} received, draining connections...`);
      
      const resourceMonitor = require('../src/managers/resource-monitor');
      const backupManager = require('../src/utilities/backup-manager');
      const healthChecker = require('../src/monitoring/health-checker');
      const updateManager = require('../src/managers/update-manager');
      const selfUpdater = require('../src/docker/self-updater');
      
      resourceMonitor.stop();
      backupManager.stop();
      healthChecker.stop();
      updateManager.stop();
      selfUpdater.stop();
      
      try {
        const dockerMaintenance = require('../src/docker/docker-maintenance');
        dockerMaintenance.stop();
      } catch { /* optional */ }
      
      try {
        const logDigest = require('../src/security/log-digest');
        logDigest.stop();
      } catch { /* optional */ }

      server.close(() => {
        log.info('shutdown', 'HTTP server closed');
        process.exit(0);
      });
      
      // Force exit after 5s if connections don't drain
      setTimeout(() => process.exit(0), 5000).unref();
    };

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

  } catch (error) {
    console.error('[FATAL] Server startup failed:', error);
    process.exit(1);
  }
})();

// Export for testing
module.exports = require('./src/app');
