/**
 * Copyright (c) 2024-2026 Тарабанов Александр Викторович
 * All rights reserved.
 * 
 * This software is proprietary and confidential.
 * Unauthorized copying, modification, or distribution is prohibited.
 * 
 * For licensing inquiries: info@hb3-accelerator.com
 * Website: https://hb3-accelerator.com
 * GitHub: https://github.com/VC-HB3-Accelerator
 */

require('dotenv').config();

// Функция для настройки NO_PROXY на основе RPC провайдеров из базы данных
async function configureNoProxyFromRpcProviders() {
  try {
    const rpcService = require('./services/rpcProviderService');
    const providers = await rpcService.getAllRpcProviders();
    
    const rpcDomains = providers
      .map(provider => provider.rpc_url)
      .filter(url => url && url.startsWith('http'))
      .map(url => {
        try {
          const urlObj = new URL(url);
          return urlObj.hostname;
        } catch (e) {
          return null;
        }
      })
      .filter(hostname => hostname)
      .filter((hostname, index, array) => array.indexOf(hostname) === index); // убираем дубликаты
    
    if (rpcDomains.length > 0) {
      const existingNoProxy = process.env.NO_PROXY || '';
      
      // Добавляем RPC домены к существующему NO_PROXY
      const newDomains = rpcDomains.filter(domain => !existingNoProxy.includes(domain));
      
      if (newDomains.length > 0) {
        process.env.NO_PROXY = existingNoProxy ? `${existingNoProxy},${newDomains.join(',')}` : newDomains.join(',');
        console.log('[Server] ✅ Добавлены RPC домены в NO_PROXY:', newDomains.join(', '));
        console.log('[Server] 📋 Обновленный NO_PROXY:', process.env.NO_PROXY);
      } else {
        console.log('[Server] ℹ️ Все RPC домены уже в NO_PROXY');
      }
    } else {
      console.warn('[Server] ⚠️ Не найдено RPC провайдеров для настройки NO_PROXY');
    }
  } catch (error) {
    console.warn('[Server] ❌ Не удалось загрузить RPC провайдеры для NO_PROXY:', error.message);
  }
}

// Экспортируем функцию для использования в других модулях
module.exports.configureNoProxyFromRpcProviders = configureNoProxyFromRpcProviders;

const { app, nonceStore } = require('./app');
const http = require('http');
const { initWSS } = require('./wsHub');
const deploymentWebSocketService = require('./services/deploymentWebSocketService');
const logger = require('./utils/logger');
// systemReadinessService удален - теперь используется WebSocket endpoint
const { initDbPool, seedAIAssistantSettings } = require('./db');
const memoryMonitor = require('./utils/memoryMonitor');

const PORT = process.env.PORT || 8000;

// console.log('Начало выполнения server.js');
// console.log('Переменная окружения PORT:', process.env.PORT);
// console.log('Используемый порт:', process.env.PORT || 8000);

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

async function startServer() {
  await initDbPool();
  
  // Настройка NO_PROXY для RPC провайдеров из базы данных
  await configureNoProxyFromRpcProviders();
  
  // Инициализация AI ассистента В ФОНЕ (неблокирующая)
  seedAIAssistantSettings().catch(error => {
    console.warn('[Server] Ollama недоступен, AI ассистент будет инициализирован позже:', error.message);
  });
  
  // ⏳ НОВОЕ: Ожидание готовности Ollama перед запуском ботов
  const { waitForOllama } = require('./utils/waitForOllama');
  
  // Запускаем ожидание Ollama в фоне (не блокируем старт сервера)
  waitForOllama({
    maxWaitTime: 4 * 60 * 1000,  // 4 минуты
    retryInterval: 5000,          // 5 секунд между попытками
    required: false               // Не обязательно - запустим боты даже без Ollama
  })
    .then((ollamaReady) => {
      if (ollamaReady) {
        console.log('[Server] ✅ Ollama готов к работе');
      } else {
        console.warn('[Server] ⚠️ Ollama не готов, боты будут работать с ограниченным функционалом AI');
      }
      
      // Инициализация ботов ПОСЛЕ ожидания Ollama
      console.log('[Server] ▶️ Импортируем BotManager...');
      const botManager = require('./services/botManager');
      console.log('[Server] ▶️ Вызываем botManager.initialize()...');
      
      return botManager.initialize();
    })
    .then(() => {
      console.log('[Server] ✅ botManager.initialize() завершен');
      
      // ✨ Запускаем AI Queue Worker после инициализации ботов
      if (process.env.USE_AI_QUEUE !== 'false') {
        const ragService = require('./services/ragService');
        ragService.startQueueWorker();
        console.log('[Server] ✅ AI Queue Worker запущен');
      }
      
      // ✨ Запускаем периодическую проверку ролей пользователей
      const authService = require('./services/auth-service');
      authService.startRoleUpdateInterval();
      console.log('[Server] ✅ Периодическая проверка ролей запущена');
      
      // ✨ Выполняем немедленную проверку ролей при запуске
      authService.updateUserRolesPeriodically().catch(error => {
        console.error('[Server] ❌ Ошибка при первоначальной проверке ролей:', error);
      });
    })
    .catch(error => {
      console.error('[Server] ❌ Ошибка инициализации:', error.message);
      logger.error('[Server] Ошибка инициализации ботов:', error);
    });
  
  console.log(`✅ Server is running on port ${PORT}`);
}

server.listen(PORT, '0.0.0.0', async () => {
  try {
    await startServer();
  } catch (error) {
    // console.error('Error starting server:', error);
    process.exit(1);
  }
});

// Обработка ошибок
process.on('unhandledRejection', (err, promise) => {
  logger.error('Unhandled Rejection:', {
    error: err.message,
    stack: err.stack,
    promise: promise
  });
  // Не завершаем процесс, так как это может быть временная ошибка подключения к БД
  // В production лучше логировать и продолжать работу
  if (process.env.NODE_ENV !== 'production') {
    console.error('Unhandled Rejection Details:', err);
  }
});

process.on('uncaughtException', (err) => {
  logger.error('Uncaught Exception:', {
    error: err.message,
    stack: err.stack
  });
  // Для критических ошибок лучше завершить процесс после логирования
  // Но даем время на логирование
  setTimeout(() => {
    process.exit(1);
  }, 1000);
});

// Запускаем мониторинг памяти в production
if (process.env.NODE_ENV === 'production') {
  memoryMonitor.start(300000); // Каждые 5 минут
  // logger.info('[Server] Мониторинг памяти запущен в production режиме'); // Убрано избыточное логирование
}

// Обработчики для корректного завершения
process.on('SIGINT', async () => {
  console.log('[Server] Получен SIGINT, завершаем работу...');
  try {
    // ✨ Останавливаем AI Queue Worker
    if (process.env.USE_AI_QUEUE !== 'false') {
      const ragService = require('./services/ragService');
      ragService.stopQueueWorker();
      console.log('[Server] ✅ AI Queue Worker остановлен');
    }
    
    // Останавливаем боты
    const botManager = require('./services/botManager');
    if (botManager.isInitialized) {
      console.log('[Server] Останавливаем боты...');
      await botManager.stop();
    }
    memoryMonitor.stop();
    await initDbPool().then(pool => pool.end());
  } catch (error) {
    console.error('[Server] Ошибка при завершении:', error);
  }
  process.exit(0);
});

process.on('SIGTERM', async () => {
  console.log('[Server] Получен SIGTERM, завершаем работу...');
  try {
    // ✨ Останавливаем AI Queue Worker
    if (process.env.USE_AI_QUEUE !== 'false') {
      const ragService = require('./services/ragService');
      ragService.stopQueueWorker();
      console.log('[Server] ✅ AI Queue Worker остановлен');
    }
    
    // Останавливаем боты
    const botManager = require('./services/botManager');
    if (botManager.isInitialized) {
      console.log('[Server] Останавливаем боты...');
      await botManager.stop();
    }
    memoryMonitor.stop();
    await initDbPool().then(pool => pool.end());
  } catch (error) {
    console.error('[Server] Ошибка при завершении:', error);
  }
  process.exit(0);
});

module.exports = app;
