/**
 * Arcadia Kernel - Entry Point
 * Sistema nativo de gerenciamento de serviços
 * 
 * V3.0 - Adicionado Service Registry + Docker Discovery
 */

import { readFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { ProcessManager } from './core/ProcessManager';
import { HealthMonitor } from './core/HealthMonitor';
import { LogAggregator } from './core/LogAggregator';
import { DashboardServer } from './dashboard/DashboardServer';
import { ServiceConfig, ServiceState } from './types';

// NOVO: Service Registry e Discovery
import { ServiceRegistry } from './registry/ServiceRegistry';
import { DockerDiscovery } from './discovery/DockerDiscovery';
import { StaticDiscovery } from './discovery/StaticDiscovery';
import { CoolifyDiscovery } from './discovery/CoolifyDiscovery';
import { XOSDiscovery } from './discovery/XOSDiscovery';
import { RegistryConfig, RegisteredService } from './registry/types';

// Suporte a ESM e CommonJS (build do Docker)
const __dirname = (() => {
  try {
    return dirname(fileURLToPath(import.meta.url));
  } catch {
    return join(process.cwd(), 'server', 'kernel');
  }
})();

export interface KernelOptions {
  configPath?: string;
  dashboard?: {
    enabled?: boolean;
    port?: number;
    host?: string;
  };
  autoStart?: boolean;
  // NOVO: Opções do Service Registry
  registry?: {
    enabled?: boolean;
    config?: Partial<RegistryConfig>;
  };
}

export class ArcadiaKernel {
  public processManager: ProcessManager;
  public healthMonitor: HealthMonitor;
  public logAggregator: LogAggregator;
  public dashboard?: DashboardServer;
  // NOVO: Service Registry
  public serviceRegistry?: ServiceRegistry;
  
  private options: Required<KernelOptions>;
  private services: ServiceConfig[] = [];
  private started = false;

  constructor(options: KernelOptions = {}) {
    this.options = {
      configPath: join(__dirname, 'config', 'services.json'),
      dashboard: {
        enabled: true,
        port: 5001,
        host: '0.0.0.0',
      },
      autoStart: false,
      // NOVO: Registry ativado por padrão
      registry: {
        enabled: true,
        config: {
          enableAutoDiscovery: true,
          discoveryInterval: 30000,
          healthCheckInterval: 15000,
        },
      },
      ...options,
    };

    // Inicializa componentes existentes
    this.logAggregator = new LogAggregator({ maxLines: 10000 });
    
    this.processManager = new ProcessManager({
      onLog: (entry) => this.logAggregator.add(entry),
      onStateChange: (serviceId, state) => {
        console.log(`[Kernel] ${serviceId}: ${state.status}`);
      },
      onHealthChange: (serviceId, health) => {
        console.log(`[Kernel] ${serviceId} health: ${health}`);
      },
    });

    this.healthMonitor = new HealthMonitor({
      onHealthChange: (serviceId, health, error) => {
        this.processManager.setHealth(serviceId, health);
        if (error) {
          console.log(`[Kernel] ${serviceId} health error: ${error}`);
        }
      },
    });

    // NOVO: Inicializa Service Registry se habilitado
    if (this.options.registry.enabled) {
      this.serviceRegistry = new ServiceRegistry({
        config: this.options.registry.config,
        discoveryProviders: [
          new StaticDiscovery(), // Descoberta via DNS interno
          new CoolifyDiscovery({ // Descoberta via API Coolify
            baseUrl: 'https://coolify.onboardbi.com.br',
            token: process.env.COOLIFY_API_TOKEN || '',
          }),
          new XOSDiscovery(), // Descoberta de serviços XOS (filas, integrações)
          new DockerDiscovery({ networkName: 'arcadia' }), // Fallback
        ],
      });

      // Escuta eventos do registry
      this.serviceRegistry.on('event', (event) => {
        console.log(`[Registry] ${event.type}: ${event.serviceId}`);
      });
    }

    // Carrega configurações
    this.loadConfig();
  }

  /**
   * Inicia o Kernel
   */
  async start(): Promise<void> {
    if (this.started) {
      return;
    }

    console.log('[Kernel] Iniciando Arcadia Kernel...');
    console.log(`[Kernel] ${this.services.length} serviços configurados (services.json)`);

    // Registra serviços no ProcessManager
    for (const config of this.services) {
      this.processManager.registerService(config);
    }

    // NOVO: Inicia Service Registry
    if (this.serviceRegistry) {
      await this.serviceRegistry.start();
    }

    // Inicia Dashboard
    if (this.options.dashboard.enabled) {
      this.dashboard = new DashboardServer(
        this.processManager,
        this.healthMonitor,
        this.logAggregator,
        this.serviceRegistry, // Passa o Registry pro Dashboard
        {
          port: this.options.dashboard.port,
          host: this.options.dashboard.host,
        }
      );
      await this.dashboard.start();
    }

    // Auto-start serviços
    if (this.options.autoStart) {
      console.log('[Kernel] Auto-iniciando serviços...');
      await this.processManager.startAll(true);
      
      // Inicia health monitoring para serviços em execução
      for (const state of this.processManager.getAllStates()) {
        if (state.status === 'running') {
          this.healthMonitor.startMonitoring(state.config.id, state);
        }
      }
    }

    this.started = true;
    console.log('[Kernel] Kernel iniciado com sucesso!');
    
    // Eventos de shutdown
    this.setupShutdownHandlers();
  }

  /**
   * Para o Kernel
   */
  async stop(): Promise<void> {
    if (!this.started) {
      return;
    }

    console.log('[Kernel] Parando Kernel...');

    // NOVO: Para Service Registry
    this.serviceRegistry?.stop();

    // Para health monitor
    this.healthMonitor.stopAll();

    // Para todos os serviços
    await this.processManager.stopAll(true);

    // Para dashboard
    await this.dashboard?.stop();

    this.started = false;
    console.log('[Kernel] Kernel parado.');
  }

  /**
   * Retorna se o kernel está rodando
   */
  isRunning(): boolean {
    return this.started;
  }

  /**
   * NOVO: Retorna estatísticas combinadas (ProcessManager + Registry)
   */
  getStats(): { processManager: any; registry: any } {
    return {
      processManager: {
        total: this.services.length,
        states: this.processManager.getAllStates(),
      },
      registry: this.serviceRegistry?.getStats(),
    };
  }

  /**
   * NOVO: Lista serviços descobertos (via Registry)
   */
  getDiscoveredServices(): RegisteredService[] {
    return this.serviceRegistry?.getServices() || [];
  }

  /**
   * Carrega configurações dos serviços
   */
  private loadConfig(): void {
    try {
      const configData = readFileSync(this.options.configPath, 'utf-8');
      const config = JSON.parse(configData);
      this.services = config.services || [];
    } catch (error) {
      console.error('[Kernel] Erro ao carregar config:', error);
      this.services = [];
    }
  }

  /**
   * Configura handlers de shutdown
   */
  private setupShutdownHandlers(): void {
    const shutdown = async (signal: string) => {
      console.log(`\n[Kernel] Sinal ${signal} recebido. Desligando...`);
      await this.stop();
      process.exit(0);
    };

    process.on('SIGTERM', () => shutdown('SIGTERM'));
    process.on('SIGINT', () => shutdown('SIGINT'));
    
    process.on('uncaughtException', (error) => {
      console.error('[Kernel] Uncaught Exception:', error);
    });
    
    process.on('unhandledRejection', (reason) => {
      console.error('[Kernel] Unhandled Rejection:', reason);
    });
  }
}

// Exporta componentes individuais
export { ProcessManager } from './core/ProcessManager';
export { HealthMonitor } from './core/HealthMonitor';
export { LogAggregator } from './core/LogAggregator';
export { DashboardServer } from './dashboard/DashboardServer';
export { KernelWebSocket } from './websocket/KernelWebSocket';
export { createKernelRoutes } from './api/routes';

// NOVO: Exports do Registry e Discovery
export { ServiceRegistry } from './registry/ServiceRegistry';
export { DockerDiscovery } from './discovery/DockerDiscovery';
export type { 
  RegisteredService, 
  ServiceFilter, 
  RegistryEvent,
  DiscoverySource,
  ServiceCategory,
} from './registry/types';

export * from './types';

// Entry point para execução direta
try {
  if (import.meta.url && import.meta.url === `file://${process.argv[1]}`) {
    const kernel = new ArcadiaKernel({
      dashboard: { enabled: true, port: 5001 },
      autoStart: true,
    });

    kernel.start().catch((error) => {
      console.error('[Kernel] Falha ao iniciar:', error);
      process.exit(1);
    });
  }
} catch {
  // No build CommonJS, o Kernel é iniciado pelo server/index.ts
}
