import { ChildProcess } from 'child_process';

/**
 * Represents the current status of a service
 */
export enum ServiceStatus {
  STOPPED = 'stopped',
  STARTING = 'starting',
  RUNNING = 'running',
  STOPPING = 'stopping',
  UNHEALTHY = 'unhealthy',
  FAILED = 'failed',
  UNKNOWN = 'unknown'
}

/**
 * Health check result from a service
 */
export interface HealthCheckResult {
  serviceName: string;
  status: 'healthy' | 'unhealthy';
  timestamp: Date;
  responseTime: number;
  details?: any;
  error?: string;
}

/**
 * Process information for a running service
 */
export interface ProcessInfo {
  serviceName: string;
  pid: number;
  command: string;
  args: string[];
  startTime: Date;
  status: 'running' | 'stopped' | 'failed';
  exitCode?: number;
  exitSignal?: string;
  exitTime?: Date;
  process?: ChildProcess;
}

/**
 * Service information for registry
 */
export interface ServiceInfo {
  name: string;
  port: number;
  healthEndpoint: string;
  dependencies?: string[];
  command?: string;
  registeredAt?: Date;
}

/**
 * Service event types for the event system
 */
export interface ServiceEvent {
  type: string;
  serviceName: string;
  timestamp?: Date;
  data?: any;
}

/**
 * Event bus interface for service communication
 */
export interface IEventBus {
  /**
   * Emit an event
   */
  emit(event: ServiceEvent): void;

  /**
   * Listen for events
   */
  on(eventType: string, listener: (event: ServiceEvent) => void): void;

  /**
   * Remove event listener
   */
  off(eventType: string, listener: (event: ServiceEvent) => void): void;

  /**
   * Get event history
   */
  getEventHistory(): ServiceEvent[];

  /**
   * Clear event history
   */
  clearHistory(): void;
}

/**
 * Health checker interface for monitoring service health
 */
export interface IHealthChecker {
  /**
   * Perform a health check on a service
   */
  checkHealth(serviceName: string, url: string): Promise<HealthCheckResult>;

  /**
   * Start monitoring a service
   */
  startMonitoring(serviceName: string, url: string, intervalMs?: number): void;

  /**
   * Stop monitoring a service
   */
  stopMonitoring(serviceName: string): void;

  /**
   * Get health status of a service
   */
  getStatus(serviceName: string): HealthCheckResult | undefined;

  /**
   * Get health status of all monitored services
   */
  getAllStatus(): Map<string, HealthCheckResult>;

  /**
   * Reset circuit breaker for a service
   */
  resetCircuitBreaker(serviceName: string): void;
}

/**
 * Process manager interface for managing service processes
 */
export interface IProcessManager {
  /**
   * Start a service process
   */
  start(serviceName: string, command: string, args: string[], cwd?: string): Promise<ProcessInfo>;

  /**
   * Stop a service process
   */
  stop(serviceName: string, signal?: NodeJS.Signals): Promise<boolean>;

  /**
   * Get process information for a service
   */
  getProcess(serviceName: string): ProcessInfo | undefined;

  /**
   * Get all processes
   */
  getAllProcesses(): ProcessInfo[];

  /**
   * Check if a service process is running
   */
  isRunning(serviceName: string): boolean;

  /**
   * Restart a service process
   */
  restart(serviceName: string): Promise<ProcessInfo>;
}

/**
 * Service registry interface for service discovery
 */
export interface IServiceRegistry {
  /**
   * Register a service
   */
  register(service: ServiceInfo): void;

  /**
   * Get service information
   */
  get(serviceName: string): ServiceInfo | undefined;

  /**
   * Get all registered services
   */
  getAll(): ServiceInfo[];

  /**
   * Unregister a service
   */
  unregister(serviceName: string): boolean;

  /**
   * Get services in dependency order (topological sort)
   */
  getDependencyOrder(): string[];
}

/**
 * Service orchestrator interface for managing multiple services
 */
export interface IServiceOrchestrator {
  /**
   * Start the service manager
   */
  start(): Promise<void>;

  /**
   * Stop the service manager
   */
  stop(): Promise<void>;

  /**
   * Start a specific service
   */
  startService(serviceName: string): Promise<void>;

  /**
   * Stop a specific service
   */
  stopService(serviceName: string): Promise<void>;

  /**
   * Get the overall status of services
   */
  getStatus(): { [serviceName: string]: ServiceStatus };

  /**
   * Get service information
   */
  getServiceInfo(): ServiceInfo[];

  /**
   * Get event history
   */
  getEventHistory(): ServiceEvent[];

  /**
   * Get event bus instance
   */
  getEventBus(): IEventBus;

  /**
   * Get service registry instance
   */
  getServiceRegistry(): IServiceRegistry;

  /**
   * Get health checker instance
   */
  getHealthChecker(): IHealthChecker;

  /**
   * Get process manager instance
   */
  getProcessManager(): IProcessManager;
}

/**
 * Error types for better error handling
 */
export class ServiceError extends Error {
  constructor(
    message: string,
    public readonly serviceName?: string,
    public readonly code?: string,
    public readonly cause?: Error
  ) {
    super(message);
    this.name = 'ServiceError';
  }
}

export class DependencyError extends ServiceError {
  constructor(
    message: string,
    serviceName?: string,
    public readonly dependency?: string,
    cause?: Error
  ) {
    super(message, serviceName, 'DEPENDENCY_ERROR', cause);
    this.name = 'DependencyError';
  }
}

export class HealthCheckError extends ServiceError {
  constructor(
    message: string,
    serviceName?: string,
    public readonly endpoint?: string,
    cause?: Error
  ) {
    super(message, serviceName, 'HEALTH_CHECK_ERROR', cause);
    this.name = 'HealthCheckError';
  }
}

export class ProcessError extends ServiceError {
  constructor(
    message: string,
    serviceName?: string,
    public readonly pid?: number,
    cause?: Error
  ) {
    super(message, serviceName, 'PROCESS_ERROR', cause);
    this.name = 'ProcessError';
  }
}

export class ConfigurationError extends Error {
  constructor(
    message: string,
    public readonly configKey?: string,
    public readonly cause?: Error
  ) {
    super(message);
    this.name = 'ConfigurationError';
  }
}

export interface HealthResponse {
  status: 'healthy' | 'unhealthy';
  service: string;
  version: string;
  timestamp: string;
  uptime: number;
  dependencies: Record<string, 'healthy' | 'unhealthy'>;
}