export type GeminiApiErrorKind = "MODEL_NOT_FOUND" | "TRANSIENT" | "OTHER";

export type GeminiApiErrorClassification = {
  kind: GeminiApiErrorKind;
  message: string;
  retryable: boolean;
};

function errorText(err: unknown): string {
  if (err instanceof Error) return err.message;
  return String(err);
}

function fullErrorBlob(err: unknown): string {
  const parts: string[] = [errorText(err)];
  const status = (err as { status?: number })?.status;
  if (typeof status === "number") parts.push(String(status));
  const code = (err as { code?: string | number })?.code;
  if (code !== undefined) parts.push(String(code));
  try {
    parts.push(JSON.stringify(err));
  } catch {
    // ignore circular refs
  }
  return parts.join(" ").toLowerCase();
}

/** 404 / model not found — 不可重试，应熔断并告警。 */
export function isGeminiModelNotFoundError(err: unknown): boolean {
  return classifyGeminiApiError(err).kind === "MODEL_NOT_FOUND";
}

export function classifyGeminiApiError(err: unknown): GeminiApiErrorClassification {
  const blob = fullErrorBlob(err);
  const message = errorText(err) || "Gemini API error";

  const modelNotFound =
    blob.includes("404") ||
    blob.includes("model not found") ||
    blob.includes("not found for api version") ||
    blob.includes("is not supported for generatecontent") ||
    blob.includes("is not found");

  if (modelNotFound) {
    return {
      kind: "MODEL_NOT_FOUND",
      message,
      retryable: false,
    };
  }

  const transient =
    blob.includes("503") ||
    blob.includes("unavailable") ||
    blob.includes("429") ||
    blob.includes("exhausted") ||
    blob.includes("rate limit");

  if (transient) {
    return { kind: "TRANSIENT", message, retryable: true };
  }

  return { kind: "OTHER", message, retryable: false };
}

export function formatGeminiModelNotFoundMessage(
  err: unknown,
  modelId: string,
): string {
  const detail = errorText(err);
  return `Gemini 模型不可用（MODEL_NOT_FOUND）：${modelId} — ${detail}`;
}
