/**
 * TTS Provider 注册表
 *
 * 集中管理所有语音合成供应商，提供熔断保护和轮转调度。
 * 与 LLM 采用相同逻辑：平等轮转，无优先级。
 */

import { ProviderRegistry } from '../../common/provider-registry';
import { ITtsProvider } from './provider.interface';
import { AliyunTtsProvider } from './aliyun.provider';
import { MockTtsProvider } from './mock.provider';
import { ttsLogger } from './tts-logger';
import { config } from '../../config';

let _registry: ProviderRegistry<ITtsProvider> | null = null;

const TTS_PROVIDER_MAP: Record<string, new (vendorKey: string, apiKey?: string, modelId?: string, ttsApiPath?: string, maxTextLength?: number) => ITtsProvider> = {
  bailian: AliyunTtsProvider,
};

/**
 * 初始化 TTS Provider 注册表（懒加载，服务启动时调用一次）
 */
export function initTtsRegistry(): ProviderRegistry<ITtsProvider> {
  if (_registry) return _registry;

  _registry = new ProviderRegistry<ITtsProvider>();

  const vendors = (config.models as any).vendors;

  // 遍历所有 vendor，为有 TTS 模型的供应商注册 TTS Provider
  if (vendors) {
    for (const [vendorKey, vendorData] of Object.entries(vendors) as [string, any][]) {
      const hasTts = vendorData.models?.some((m: any) => m.input?.includes('tts') && m.enabled);
      if (!hasTts) continue;

      // 1. 匹配映射表中的 key
      const ProviderClass = TTS_PROVIDER_MAP[vendorKey];

      if (!ProviderClass) {
        ttsLogger.registry('skip', vendorKey, '无对应 Provider 实现');
        continue;
      }

      try {
        // 从 models.json 提取 TTS 模型配置
        const ttsModels = (vendorData.models || [])
          .filter((m: any) => m.input?.includes('tts') && m.enabled);
        const ttsModel = ttsModels[0]; // 取第一个启用的 TTS 模型
        const modelId = ttsModel?.id;
        // 模型有独立 apiPath 时用它，否则用 vendor 级 ttsApiPath
        const ttsApiPath = ttsModel?.apiPath
          ? `https://dashscope.aliyuncs.com${ttsModel.apiPath}`
          : vendorData.ttsApiPath;

        const maxTextLen = ttsModel?.maxTextLength;
        const provider = new ProviderClass(vendorKey, vendorData.apiKey, modelId, ttsApiPath, maxTextLen);
        _registry.register(provider, {
          enabled: true,
          breakerConfig: { name: `${vendorKey}-tts`, failureThreshold: 3, cooldownMs: 60000 },
        });
        ttsLogger.registry('register', provider.name, `model=${modelId}, vendor=${vendorKey}`);
      } catch (e) {
        ttsLogger.error(`注册 ${vendorKey} TTS 失败`, e as Error);
      }
    }
  }

  // Mock Provider 兜底（当前已禁用，需要时改为 enabled: true）
  if (!_registry.get('mock-tts')) {
    const mockProvider = new MockTtsProvider();
    _registry.register(mockProvider, {
      enabled: false,
      breakerConfig: { name: 'mock-tts', failureThreshold: 999, cooldownMs: 1000 },
    });
    ttsLogger.registry('register', mockProvider.name, '已禁用');
  }

  ttsLogger.info(`TTS Registry 初始化完成，共 ${_registry.size} 个 Provider`);
  return _registry;
}

/**
 * 获取 TTS Provider 注册表
 */
export function getTtsRegistry(): ProviderRegistry<ITtsProvider> {
  if (!_registry) {
    return initTtsRegistry();
  }
  return _registry;
}

/**
 * 按名称获取特定 TTS Provider（带熔断保护）
 * @param preferredName 优先使用的 Provider 名称
 * @returns 返回可用的 Provider 节点，如果优先的已熔断则返回下一个
 */
export function getAvailableTtsProvider(preferredName?: string): {
  provider: ITtsProvider;
  node: import('../../common/provider-registry').ProviderNode<ITtsProvider>;
} {
  const registry = getTtsRegistry();

  if (preferredName) {
    const preferredNode = registry.get(preferredName);
    if (preferredNode && preferredNode.enabled && !preferredNode.breaker.isOpen() && !preferredNode.exhausted) {
      return { provider: preferredNode.provider, node: preferredNode };
    }
    // 优先的不可用，尝试下一个
    const next = registry.getNextAvailable(preferredName);
    if (next) {
      ttsLogger.fallback(preferredName, next.provider.name, '优先 Provider 不可用');
      return { provider: next.provider, node: next };
    }
  }

  // 无偏好，用最高优先级
  const primary = registry.getPrimary();
  if (!primary) {
    throw new Error('没有可用的 TTS Provider');
  }
  return { provider: primary.provider, node: primary };
}

// ============ 定时健康检查 ============

let _healthCheckTimer: ReturnType<typeof setInterval> | null = null;
const HEALTH_CHECK_INTERVAL_MS = 30_000; // 30s

/** 启动 TTS 定时健康检查 */
export function startTtsHealthCheck(): void {
  if (_healthCheckTimer) return;

  _healthCheckTimer = setInterval(async () => {
    const registry = getTtsRegistry();

    // 检查熔断恢复
    const broken = registry.listBroken();
    for (const node of broken) {
      try {
        const state = node.breaker.getState();
        if (state === 'HALF_OPEN') {
          ttsLogger.healthCheck(node.provider.name, 'still_down', '熔断冷却期已过，尝试探测...');
          const healthy = await node.provider.healthCheck?.();
          if (healthy) {
            node.breaker.reset();
            ttsLogger.circuitBreaker(node.provider.name, 'closed', '探测成功');
          } else {
            ttsLogger.healthCheck(node.provider.name, 'still_down', '探测失败，继续熔断');
          }
        }
      } catch {
        // 探测异常，保持熔断
      }
    }

    // 检查额度耗尽恢复（已标记 exhausted 的供应商恢复探测）
    const exhausted = registry.listExhausted();
    for (const node of exhausted) {
      try {
        // 额度耗尽不带 TTL，由健康检查探测恢复
        const healthy = await node.provider.healthCheck?.();
        if (healthy) {
          registry.clearExhausted(node.provider.name);
          ttsLogger.quota(node.provider.name, 'recovered');
        }
      } catch {
        // 探测失败，保持耗尽
      }
    }
  }, HEALTH_CHECK_INTERVAL_MS);

  ttsLogger.info(`TTS HealthCheck 已启动，间隔 ${HEALTH_CHECK_INTERVAL_MS / 1000}s`);
}

/** 停止 TTS 定时健康检查 */
export function stopTtsHealthCheck(): void {
  if (_healthCheckTimer) {
    clearInterval(_healthCheckTimer);
    _healthCheckTimer = null;
    ttsLogger.info('TTS HealthCheck 已停止');
  }
}
