import type { MetricsCollector, InstanceMetrics } from './metrics-collector.js';
import type { McpOrchestrator } from './orchestrator.js';

export interface SystemHealth {
  overallStatus: 'healthy' | 'degraded' | 'unhealthy';
  totalInstances: number;
  healthyCount: number;
  unhealthyCount: number;
  unknownCount: number;
  runtimeAvailable: boolean;
  aggregateErrorRate: number;
  averageUptime: number;
  timestamp: string;
}

export interface InstanceHealth {
  instanceId: string;
  status: InstanceMetrics['status'];
  uptime: number;
  requestCount: number;
  errorCount: number;
  errorRate: number;
  averageLatencyMs: number;
  lastRequestAt: string | null;
}

export class HealthAggregator {
  constructor(
    private metricsCollector: MetricsCollector,
    private orchestrator: McpOrchestrator,
  ) {}

  async getOverview(): Promise<SystemHealth> {
    const runtimeAvailable = await this.orchestrator.ping().catch(() => false);
    const allMetrics = this.metricsCollector.getAllMetrics();

    let healthyCount = 0;
    let unhealthyCount = 0;
    let unknownCount = 0;
    let totalErrors = 0;
    let totalRequests = 0;
    let totalUptime = 0;

    for (const m of allMetrics) {
      switch (m.status) {
        case 'healthy':
          healthyCount++;
          break;
        case 'unhealthy':
          unhealthyCount++;
          break;
        default:
          unknownCount++;
      }
      totalErrors += m.errorCount;
      totalRequests += m.requestCount;
      totalUptime += m.uptime;
    }

    const totalInstances = allMetrics.length;
    const aggregateErrorRate = totalRequests > 0 ? totalErrors / totalRequests : 0;
    const averageUptime = totalInstances > 0 ? totalUptime / totalInstances : 0;

    let overallStatus: SystemHealth['overallStatus'] = 'healthy';
    if (!runtimeAvailable || (totalInstances > 0 && unhealthyCount === totalInstances)) {
      overallStatus = 'unhealthy';
    } else if (unhealthyCount > 0 || unknownCount > 0) {
      overallStatus = 'degraded';
    }

    return {
      overallStatus,
      totalInstances,
      healthyCount,
      unhealthyCount,
      unknownCount,
      runtimeAvailable,
      aggregateErrorRate,
      averageUptime,
      timestamp: new Date().toISOString(),
    };
  }

  getInstanceHealth(instanceId: string): InstanceHealth | undefined {
    const m = this.metricsCollector.getMetrics(instanceId);
    if (!m) return undefined;

    return {
      instanceId: m.instanceId,
      status: m.status,
      uptime: m.uptime,
      requestCount: m.requestCount,
      errorCount: m.errorCount,
      errorRate: this.metricsCollector.getErrorRate(instanceId),
      averageLatencyMs: this.metricsCollector.getAverageLatency(instanceId),
      lastRequestAt: m.lastRequestAt?.toISOString() ?? null,
    };
  }
}
