/**
 * 成本估算 —— 纯函数，`AiCallRunner` 与助手共用**同一份**口径。
 *
 * ⚠️ 抽出来是因为它是**计价**逻辑：抄第二份必然会漂，而漂了之后报表上看不出任何异常
 *   （同一类 bug 2026-08-13 栽过一次：换 qwen 旗舰后成本被低报约四倍）。
 */

export interface ModelPrice {
  /** ¥/M tokens —— 输入里命中 vendor prompt cache 的部分 */
  inHit: number;
  /** ¥/M tokens —— 输入里未命中的部分 */
  inMiss: number;
  /** ¥/M tokens —— 输出 */
  out: number;
}

/** 价目表里查不到时的兜底价（与历史行为一致：按 deepseek-v4-pro 估）。 */
export const FALLBACK_PRICE: ModelPrice = { inHit: 0.5, inMiss: 3.6, out: 25 };

export interface CostResult {
  yuan: number;
  /** 价目表里没有这个模型 —— 调用方要吭声，⛔ 别静默 */
  priceMissing: boolean;
}

export function estimateCostYuan(
  priceTable: Record<string, ModelPrice>,
  modelId: string,
  promptTokens: number,
  completionTokens: number,
  cachedInputTokens = 0,
): CostResult {
  const p = priceTable[modelId];
  const price = p ?? priceTable['deepseek-v4-pro'] ?? FALLBACK_PRICE;
  // 防御:cached > prompt 不该发生,clamp
  const hit = Math.min(Math.max(0, cachedInputTokens), Math.max(0, promptTokens));
  const miss = Math.max(0, promptTokens - hit);
  const yuan =
    (hit * price.inHit + miss * price.inMiss + Math.max(0, completionTokens) * price.out) /
    1_000_000;
  return { yuan: Math.max(0, yuan), priceMissing: !p };
}
