import { getLogger } from '@stock-bot/logger';
import { MongoDBClient } from '@stock-bot/mongodb';
import { PostgreSQLClient } from '@stock-bot/postgres';
import { createCache } from '@stock-bot/cache';
import { QueueManager, Queue } from '@stock-bot/queue';
import { IServiceContainer } from '@stock-bot/handlers';
import { ModeManager } from './core/ModeManager';
import { MarketDataService } from './services/MarketDataService';
import { ExecutionService } from './services/ExecutionService';
import { AnalyticsService } from './services/AnalyticsService';
import { StorageService } from './services/StorageService';
import { StrategyManager } from './strategies/StrategyManager';
import { BacktestEngine } from './backtest/BacktestEngine';
import { RustBacktestAdapter } from './backtest/RustBacktestAdapter';
import { PaperTradingManager } from './paper/PaperTradingManager';

/**
 * Creates a simplified service container without the DI framework
 * All configuration comes from the config object
 */
export async function createContainer(config: any): Promise<any> {
  const logger = getLogger('orchestrator');
  
  // Initialize database clients if enabled
  let mongoClient: MongoDBClient | undefined;
  if (config.database.mongodb.enabled) {
    mongoClient = new MongoDBClient(config.database.mongodb, logger);
    await mongoClient.connect();
  }
  
  let postgresClient: PostgreSQLClient | undefined;
  if (config.database.postgres.enabled) {
    postgresClient = new PostgreSQLClient({
      host: config.database.postgres.host,
      port: config.database.postgres.port,
      database: config.database.postgres.database,
      username: config.database.postgres.user,
      password: config.database.postgres.password,
      poolSettings: {
        min: 1,
        max: config.database.postgres.poolSize || 20,
        idleTimeoutMillis: config.database.postgres.idleTimeout || 10000
      }
    });
    await postgresClient.connect();
  }
  
  // Initialize cache if enabled
  let cache: any;
  if (config.database.dragonfly.enabled) {
    cache = createCache({
      redisConfig: {
        host: config.database.dragonfly.host,
        port: config.database.dragonfly.port,
        db: config.database.dragonfly.db,
        keyPrefix: config.database.dragonfly.keyPrefix
      },
      ttl: 3600,
      enableMetrics: true
    });
  }
  
  // Initialize queue if enabled
  let queue: Queue | undefined;
  let queueManager: QueueManager | undefined;
  if (config.queue.enabled) {
    queue = new Queue('orchestrator', {
      redis: {
        host: config.queue.redis.host,
        port: config.queue.redis.port,
        db: config.queue.redis.db
      }
    });
    queueManager = new QueueManager(config, logger);
  }
  
  // Create base services container
  const services: IServiceContainer = {
    logger,
    cache,
    mongodb: mongoClient,
    postgres: postgresClient,
    queue,
    queueManager,
    config,
    custom: {}
  };
  
  // Create orchestrator services
  const storageService = new StorageService(
    services,
    mongoClient!,
    postgresClient!,
    null // QuestDB not needed for now
  );
  
  const marketDataService = new MarketDataService(services);
  const executionService = new ExecutionService(services, storageService);
  const analyticsService = new AnalyticsService(services, storageService);
  const strategyManager = new StrategyManager(services);
  
  // Add strategy manager to custom services early so RustBacktestAdapter can access it
  services.custom.StrategyManager = strategyManager;
  
  // Use Rust backtest engine if configured
  const useRustEngine = config.services?.orchestrator?.backtesting?.useRustEngine !== false;
  const backtestEngine = useRustEngine 
    ? new RustBacktestAdapter(services)
    : new BacktestEngine(services, storageService, strategyManager);
  const paperTradingManager = new PaperTradingManager(
    services,
    storageService,
    marketDataService,
    executionService
  );
  const modeManager = new ModeManager(
    services,
    marketDataService,
    executionService,
    storageService
  );
  
  // Store custom services (before creating RustBacktestAdapter)
  services.custom = {
    StorageService: storageService,
    MarketDataService: marketDataService,
    ExecutionService: executionService,
    AnalyticsService: analyticsService,
    StrategyManager: strategyManager,
    BacktestEngine: backtestEngine,
    PaperTradingManager: paperTradingManager,
    ModeManager: modeManager
  };
  
  // Setup event listeners after all services are registered
  strategyManager.setupEventListeners();
  
  // Initialize mode manager with configured default mode
  const serviceConfig = config.services?.orchestrator || {};
  await modeManager.initializeMode({
    mode: serviceConfig.defaultMode || 'paper',
    startingCapital: serviceConfig.paperTradingCapital || 100000
  });
  
  return services;
}