// src/server/app.ts
// Main Fastify server entry point

import 'dotenv/config';
import Fastify from 'fastify';
import cookie from '@fastify/cookie';
import corsPlugin from './shared/plugins/cors';
import jwtPlugin from './shared/plugins/jwt';
import { socketPlugin } from './shared/plugins/socket';
import { errorHandler } from './shared/plugins/error-handler';
import { loggerService } from './shared/lib/logger';
import { initializeCronJobs } from './shared/cron/index.js';
import rbacPlugin from './shared/plugins/rbac';
import { db } from './shared/db/client';
import { emitter } from './shared/lib/events';
import { getEnabledModules } from './config/modules';

// 🔥 GLOBAL CRASH GUARD - перехватчики фатальных ошибок
process.on('uncaughtException', (err) => {
  console.error('\n🔥🔥🔥 [FATAL CRASH: uncaughtException]');
  console.error(err.stack);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  console.error('\n🔥🔥🔥 [FATAL CRASH: unhandledRejection]');
  console.error('Reason:', reason);
  process.exit(1);
});

// Initialize logger for app initialization
const appLogger = loggerService.get('SYSTEM');

// 🔥 ИМПОРТЫ ДЛЯ ФИКСА (НЕ импортируем встроенные компиляторы, они глючат)
import { z } from 'zod';
import { 
  serializerCompiler, 
  validatorCompiler, 
  ZodTypeProvider 
} from 'fastify-type-provider-zod';

// 🔥 ИНИЦИАЛИЗАЦИЯ С ТИПАМИ
const fastify = Fastify({
  logger: false,
}).withTypeProvider<ZodTypeProvider>();

(async () => {
  try {
    appLogger.info('🔧 Starting server initialization...');
    
    appLogger.info('🔧 Registering CORS plugin...');
    await fastify.register(corsPlugin);
    appLogger.info('✅ CORS plugin registered');
    
    appLogger.info('🔧 Registering Cookie plugin...');
    await fastify.register(cookie);
    appLogger.info('✅ Cookie plugin registered');

    // Decorate fastify with db instance for DI
    fastify.decorate('db', db);
    appLogger.info('✅ DB instance decorated');

    // Decorate fastify with emitter instance for cross-slice communication
    fastify.decorate('emitter', emitter);
    appLogger.info('✅ Emitter instance decorated');

    appLogger.info('🔧 Registering JWT plugin...');
    await fastify.register(jwtPlugin);
    appLogger.info('✅ JWT plugin registered');
    
    appLogger.info('🔧 Registering RBAC plugin...');
    await fastify.register(rbacPlugin);
    appLogger.info('✅ RBAC plugin registered');
    
    appLogger.info('🔧 Registering Socket.io plugin...');
    await fastify.register(socketPlugin);
    appLogger.info('✅ Socket.io plugin registered');
    
    appLogger.info('🔧 Setting up centralized error handler...');
    fastify.setErrorHandler(errorHandler);
    appLogger.info('✅ Error handler registered');

    // Add onResponse hook for HTTP logging
    fastify.addHook('onResponse', async (request, reply) => {
      const httpLogger = loggerService.get('HTTP');
      const method = request.method;
      const url = request.url;
      const statusCode = reply.statusCode;
      const responseTime = (reply as any).elapsedTime;

      // Log based on status code
      if (statusCode >= 500) {
        httpLogger.error(`${method} ${url} - ${statusCode} (${responseTime.toFixed(2)}ms)`);
      } else if (statusCode >= 400) {
        httpLogger.warn(`${method} ${url} - ${statusCode} (${responseTime.toFixed(2)}ms)`);
      } else {
        httpLogger.info(`${method} ${url} - ${statusCode} (${responseTime.toFixed(2)}ms)`);
      }
    });
    appLogger.info('✅ HTTP logging hook registered');

    appLogger.info('🔧 Setting up Zod validators (Custom Logic)...');
    fastify.setValidatorCompiler(validatorCompiler);
    fastify.setSerializerCompiler(serializerCompiler);
    appLogger.info('✅ Zod validators configured');
    
    // Dynamic module registration with Feature Toggling support
    appLogger.info('🔧 Loading feature modules...');
    const enabledModules = getEnabledModules();
    const registeredPlugins = new Set<string>();
    
    for (const module of enabledModules) {
      appLogger.info(`🔧 Registering ${module.name} plugin...`);
      try {
        // Skip if this plugin path has already been registered
        if (registeredPlugins.has(module.path)) {
          appLogger.info(`⏭️  ${module.name} plugin already registered (path: ${module.path}), skipping...`);
          continue;
        }
        
        const plugin = await import(module.path);
        await fastify.register(plugin.default);
        registeredPlugins.add(module.path);
        appLogger.info(`✅ ${module.name} plugin registered`);
      } catch (error) {
        appLogger.error(`Failed to register ${module.name} plugin:`, error);
        throw error;
      }
    }
    
    appLogger.info(`✅ All ${enabledModules.length} feature modules registered (${registeredPlugins.size} unique plugins)`);
    
    appLogger.info('🔧 Setting up routes...');

    // Health check route
    fastify.get('/health', async () => {
      return { success: true, message: 'Server is running' };
    });

    // Debug route to list all routes
    fastify.get('/debug/routes', async () => {
      const routes: string[] = [];
      fastify.printRoutes({ method: 'GET', includeHooks: false, commonPrefix: false, includeMeta: false })
        .split('\n')
        .forEach((line: string) => {
          if (line.trim()) routes.push(line.trim());
        });
      return { success: true, data: routes };
    });

    // Config route to get enabled modules
    fastify.get(
      '/api/config/modules',
      {
        schema: {
          response: {
            200: z.array(z.string()),
          },
        },
      },
      async () => {
        return enabledModules.map((module) => module.name);
      }
    );

    appLogger.info('✅ Routes set up successfully');
    
    // Initialize cron jobs
    appLogger.info('🔧 Initializing cron jobs...');
    initializeCronJobs();
    appLogger.info('✅ Cron jobs initialized');
    
    // Start server
    const port = Number(process.env.PORT) || 3000;
    appLogger.info(`🔧 Starting server on port ${port}...`);
    await fastify.listen({ port, host: '0.0.0.0' });
    appLogger.info(`🚀 Server listening on port ${port}`);
    appLogger.info(`🔗 API available at: http://localhost:${port}/api/auth/login`);
  } catch (err) {
    console.error('❌ Error starting server:', err);
    appLogger.error('Error starting server:', err);
    process.exit(1);
  }
})();