<?php

namespace XZD\AI\V5\AI;

/**
 * AI API 错误分类器 — 将原始错误消息映射为语义化错误码
 *
 * 原本存在 OpenAICompatibleProvider::classifyError() 静态方法中，
 * ClaudeProvider 和 GeminiProvider 跨类调用产生反向依赖。
 * V3.1.7 提取为独立类，消除反向依赖。
 */
class ErrorClassifier
{
    /**
     * 对 API 错误消息进行分类，返回语义化错误码
     *
     * @param string $errMsg  原始错误消息
     * @param int    $httpCode HTTP 状态码
     * @return string 语义化错误码: insufficient_balance|auth_failed|rate_limited|model_not_found|{httpCode}
     */
    public static function classify(string $errMsg, int $httpCode): string
    {
        $lower = strtolower($errMsg);

        // 余额不足
        if (str_contains($lower, 'insufficient balance')
            || str_contains($lower, '余额不足')
            || str_contains($lower, 'quota')
            || str_contains($lower, 'billing')
            || str_contains($lower, 'exceeded your current balance')
            || str_contains($lower, 'account balance')
        ) {
            return 'insufficient_balance';
        }

        // 认证失败
        if ($httpCode === 401 || $httpCode === 403
            || str_contains($lower, 'unauthorized')
            || str_contains($lower, 'invalid api key')
            || str_contains($lower, 'invalid token')
            || str_contains($lower, 'authentication')
            || str_contains($lower, 'incorrect api key')
        ) {
            return 'auth_failed';
        }

        // 速率限制
        if ($httpCode === 429 || str_contains($lower, 'rate limit') || str_contains($lower, 'too many requests')) {
            return 'rate_limited';
        }

        // 模型不存在/不可用
        if (str_contains($lower, 'model') && (str_contains($lower, 'not found') || str_contains($lower, 'not exist') || str_contains($lower, 'does not exist'))) {
            return 'model_not_found';
        }

        return (string) $httpCode;
    }
}
