/**
 * 通用 Provider 注册表
 *
 * 统一管理 TTS 和 LLM 供应商的生命周期：
 * - 注册/注销
 * - 按名称/供应商查找
 * - 状态查询（可用/禁用/熔断/额度耗尽）
 * - 轮转调度（平等，无优先级）
 *
 * 每个 Provider 节点包含：
 *   - provider: 实际的 Provider 实例
 *   - breaker: 该 Provider 专属的熔断器
 *   - enabled: 是否启用
 *   - exhausted: 是否额度耗尽
 */

import { CircuitBreaker, CircuitBreakerConfig } from './circuit-breaker';

export interface ProviderNode<T> {
  /** Provider 实例 */
  provider: T;
  /** 熔断器 */
  breaker: CircuitBreaker;
  /** 是否启用（false = 不参与调度） */
  enabled: boolean;
  /** 是否额度耗尽（true = 已耗尽，跳过） */
  exhausted: boolean;
  /** 额度耗尽原因 */
  exhaustedReason?: string;
  /** 额度耗尽时间（Unix ms） */
  exhaustedAt?: number;
}

export type ProviderFilter<T> = (node: ProviderNode<T>, index: number) => boolean;

export class ProviderRegistry<T extends { readonly name: string; readonly vendor: string }> {
  private nodes: ProviderNode<T>[] = [];

  /**
   * 注册一个 Provider
   */
  register(
    provider: T,
    options?: {
      enabled?: boolean;
      breakerConfig?: Partial<CircuitBreakerConfig>;
    }
  ): void {
    const existingIdx = this.nodes.findIndex(n => n.provider.name === provider.name);
    const node: ProviderNode<T> = {
      provider,
      enabled: options?.enabled ?? true,
      exhausted: false,
      breaker: new CircuitBreaker({
        name: provider.name,
        ...(options?.breakerConfig || {}),
      }),
    };

    if (existingIdx >= 0) {
      this.nodes[existingIdx] = node;
    } else {
      this.nodes.push(node);
    }
  }

  /** 注销 Provider */
  unregister(name: string): boolean {
    const idx = this.nodes.findIndex(n => n.provider.name === name);
    if (idx >= 0) {
      this.nodes.splice(idx, 1);
      return true;
    }
    return false;
  }

  /** 按名称查找 */
  get(name: string): ProviderNode<T> | undefined {
    return this.nodes.find(n => n.provider.name === name);
  }

  /** 按供应商 key 查找 */
  getByVendor(vendor: string): ProviderNode<T> | undefined {
    return this.nodes.find(n => n.provider.vendor === vendor);
  }

  /** 获取所有节点 */
  list(filter?: ProviderFilter<T>): ProviderNode<T>[] {
    return filter ? this.nodes.filter((n, i) => filter(n, i)) : [...this.nodes];
  }

  /** 获取所有可用节点（启用 + 未熔断 + 未耗尽） */
  listAvailable(): ProviderNode<T>[] {
    return this.nodes.filter(n => n.enabled && !n.breaker.isOpen() && !n.exhausted);
  }

  /** 获取所有已启用节点 */
  listEnabled(): ProviderNode<T>[] {
    return this.nodes.filter(n => n.enabled);
  }

  /** 获取所有已熔断节点 */
  listBroken(): ProviderNode<T>[] {
    return this.nodes.filter(n => n.enabled && n.breaker.isOpen());
  }

  /** 获取所有额度耗尽的节点 */
  listExhausted(): ProviderNode<T>[] {
    return this.nodes.filter(n => n.exhausted);
  }

  /**
   * 标记供应商额度耗尽
   * @param name 供应商名称
   * @param reason 耗尽原因
   * @param ttlMs 可选TTL，0 = 永不过期（需手动恢复）
   */
  markExhausted(name: string, reason: string, ttlMs: number = 0): void {
    const node = this.get(name);
    if (!node) return;
    node.exhausted = true;
    node.exhaustedReason = reason;
    node.exhaustedAt = Date.now();
    console.log(`[Registry] 供应商 ${name} 额度耗尽: ${reason}${ttlMs > 0 ? `，${ttlMs / 1000}s后自动恢复` : ''}`);

    if (ttlMs > 0) {
      setTimeout(() => this.clearExhausted(name), ttlMs);
    }
  }

  /** 清除额度耗尽标记 */
  clearExhausted(name: string): boolean {
    const node = this.get(name);
    if (!node) return false;
    if (!node.exhausted) return false;
    node.exhausted = false;
    node.exhaustedReason = undefined;
    node.exhaustedAt = undefined;
    console.log(`[Registry] 供应商 ${name} 额度已恢复`);
    return true;
  }

  /**
   * 从当前 Provider 轮转到下一个可用 Provider（平等轮转）
   */
  getNextAvailable(currentName: string): ProviderNode<T> | undefined {
    const available = this.listAvailable();
    if (available.length === 0) return undefined;

    const currentIdx = available.findIndex(n => n.provider.name === currentName);
    if (currentIdx === -1) {
      return available[0];
    }
    return available[(currentIdx + 1) % available.length];
  }

  /** 获取第一个可用的 Provider */
  getPrimary(): ProviderNode<T> | undefined {
    return this.listAvailable()[0];
  }

  /** 检查所有 Provider 健康状态 */
  async healthCheckAll(checkFn: (provider: T) => Promise<boolean>): Promise<Map<string, boolean>> {
    const results = new Map<string, boolean>();
    for (const node of this.nodes) {
      if (!node.enabled) {
        results.set(node.provider.name, false);
        continue;
      }
      try {
        const healthy = await checkFn(node.provider);
        results.set(node.provider.name, healthy);
        if (!healthy) {
          node.breaker['onFailure']?.();
        }
      } catch {
        results.set(node.provider.name, false);
      }
    }
    return results;
  }

  /** Provider 数量 */
  get size(): number {
    return this.nodes.length;
  }

  /** 重置所有熔断器 */
  resetAllBreakers(): void {
    this.nodes.forEach(n => n.breaker.reset());
  }

  /** 重置所有额度耗尽标记 */
  clearAllExhausted(): void {
    this.nodes.forEach(n => {
      n.exhausted = false;
      n.exhaustedReason = undefined;
      n.exhaustedAt = undefined;
    });
  }

  /** 获取状态摘要 */
  getStatus(): Array<{
    name: string;
    vendor: string;
    enabled: boolean;
    exhausted: boolean;
    exhaustedReason?: string;
    state: string;
  }> {
    return this.nodes.map(n => ({
      name: n.provider.name,
      vendor: n.provider.vendor,
      enabled: n.enabled,
      exhausted: n.exhausted,
      exhaustedReason: n.exhaustedReason,
      state: n.breaker.getState(),
    }));
  }
}