export interface AppConfig {
  nodeEnv: 'development' | 'test' | 'production';
  port: number;
  logLevel: string;
  database: { url: string };
  redis: { url: string };
  jwt: {
    secret: string;
    refreshSecret: string;
    expiresIn: string;
    refreshExpiresIn: string;
  };
  ai: {
    /// DeepSeek 直连 API key(国内 endpoint,合规)。从 https://platform.deepseek.com/api_keys 取
    deepseekApiKey: string;
    /// DeepSeek base URL(默认官方;私有 / 镜像 endpoint 时覆盖)
    deepseekBaseUrl: string;
    /// 默认主力模型(deepseek-v4-pro / deepseek-v4-flash)
    defaultModel: string;
    /// Gemini API key(Google AI Studio;海外需可达 generativelanguage.googleapis.com)
    geminiApiKey: string;
    /// Gemini base URL(空=SDK 默认;走代理 / 镜像 endpoint 时覆盖)
    geminiBaseUrl: string;
    /// Gemini 默认模型(前端传逻辑键 "gemini" 时解析到此具体型号)
    geminiDefaultModel: string;
    /// DashScope(阿里云百炼)API key — Qwen-Omni-Realtime 实时教练用;只服务端,绝不下发浏览器
    dashscopeApiKey: string;
    /// Qwen Omni 实时模型名(实时坐席辅助教练)
    qwenOmniModel: string;
    /// Gemini Live 实时模型名(实时教练可选 provider)
    geminiLiveModel: string;
    /// LLM 调用上限(秒),防卡死
    requestTimeoutSec: number;
    /// 价格表(¥/M tokens)— 从 AI_PRICE_TABLE_JSON env 读;调价时改 env 重启即可
    priceTable: Record<string, { inHit: number; inMiss: number; out: number }>;
  };
  alert: { webhookUrl: string };
  cors: { origins: string[] };
  exchangeCodeTtlSeconds: number;
}

export function loadConfig(): AppConfig {
  return {
    nodeEnv: (process.env.NODE_ENV as AppConfig['nodeEnv']) ?? 'development',
    port: Number(process.env.PORT ?? 3001),
    logLevel: process.env.LOG_LEVEL ?? 'info',
    database: {
      url: required('DATABASE_URL'),
    },
    redis: {
      url: required('REDIS_URL'),
    },
    jwt: {
      secret: required('JWT_SECRET'),
      refreshSecret: required('JWT_REFRESH_SECRET'),
      expiresIn: process.env.JWT_EXPIRES_IN ?? '2h',
      refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN ?? '7d',
    },
    ai: {
      deepseekApiKey: process.env.DEEPSEEK_API_KEY ?? '',
      deepseekBaseUrl: process.env.DEEPSEEK_BASE_URL ?? 'https://api.deepseek.com',
      defaultModel: process.env.AI_DEFAULT_MODEL ?? 'deepseek-v4-flash',
      geminiApiKey: process.env.GEMINI_API_KEY ?? '',
      geminiBaseUrl: process.env.GEMINI_BASE_URL ?? '',
      geminiDefaultModel: process.env.GEMINI_DEFAULT_MODEL ?? 'gemini-3.5-flash',
      dashscopeApiKey: process.env.DASHSCOPE_API_KEY ?? '',
      qwenOmniModel: process.env.QWEN_OMNI_MODEL ?? 'qwen3-omni-flash-realtime',
      geminiLiveModel: process.env.GEMINI_LIVE_MODEL ?? 'gemini-3.1-flash-live-preview',
      requestTimeoutSec: Number(process.env.AI_REQUEST_TIMEOUT_SEC ?? 60),
      priceTable: parsePriceTable(process.env.AI_PRICE_TABLE_JSON),
    },
    alert: {
      webhookUrl: process.env.ALERT_WEBHOOK_URL ?? '',
    },
    cors: {
      origins: (process.env.CORS_ORIGINS ?? '')
        .split(',')
        .map((s) => s.trim())
        .filter(Boolean),
    },
    exchangeCodeTtlSeconds: Number(process.env.EXCHANGE_CODE_TTL_SECONDS ?? 60),
  };
}

/**
 * AI 价格表 — 从 env JSON 读,失败兜底默认值。
 *
 * 单位:¥/M tokens(已按汇率换算,DeepSeek 公开价 USD * 7.2)。
 *   inHit:  输入命中 prompt cache 的部分(便宜 ~7x)
 *   inMiss: 输入未命中(全价)
 *   out:    输出(含 reasoning,DeepSeek 统一计费)
 *
 * 调价流程:
 *   1. 改 .env 里 AI_PRICE_TABLE_JSON
 *   2. 重启 service
 *   3. 历史 invocation 已落库 costYuan 不动(快照,不被新价污染)
 *   4. 新调用按新价计
 */
function parsePriceTable(raw: string | undefined): Record<string, { inHit: number; inMiss: number; out: number }> {
  const DEFAULT = {
    'deepseek-v4-pro':   { inHit: 0.5,  inMiss: 3.6, out: 25 },
    'deepseek-v4-flash': { inHit: 0.07, inMiss: 0.5, out: 2 },
    // Gemini Flash 估算价(×7.2 汇率)— 实际调价改 AI_PRICE_TABLE_JSON env
    'gemini-3.5-flash':  { inHit: 0.54, inMiss: 2.16, out: 18 },
    'gemini-2.5-flash':  { inHit: 0.54, inMiss: 2.16, out: 18 },
  };
  if (!raw) return DEFAULT;
  try {
    const parsed = JSON.parse(raw) as Record<string, { inHit: number; inMiss: number; out: number }>;
    // 简易校验:确保每条都有 3 个 number 字段
    for (const [k, v] of Object.entries(parsed)) {
      if (typeof v.inHit !== 'number' || typeof v.inMiss !== 'number' || typeof v.out !== 'number') {
        throw new Error(`invalid entry for model "${k}"`);
      }
    }
    return parsed;
  } catch (err) {
    // eslint-disable-next-line no-console
    console.warn(`AI_PRICE_TABLE_JSON 解析失败,回落到默认值:`, err instanceof Error ? err.message : err);
    return DEFAULT;
  }
}

function required(name: string): string {
  const v = process.env[name];
  if (!v || v.trim() === '') {
    throw new Error(`Missing required env var: ${name}`);
  }
  return v;
}

// Optional: keep a no-op schema slot for ConfigModule API symmetry.
export const configValidationSchema = undefined;
