package tech.easyflow.ai.service.capability;

import java.util.Locale;
import java.util.regex.Pattern;

/**
 * 未命中模型目录时使用的保守命名规则。
 */
final class ModelCapabilityNameRules {

    private static final Pattern RERANK_PATTERN = Pattern.compile(
            "(^|[/_.:-])rerank(?:er)?($|[/_.:-])");
    private static final Pattern EMBEDDING_PATTERN = Pattern.compile(
            "(^|[/_.:-])(embedding|embed)($|[/_.:-])|(^|/)bge-m3($|[/_.:-])"
                    + "|(^|/)(e5|gte)(-|$)");
    private static final Pattern VISION_PATTERN = Pattern.compile(
            "(^|[/_.:-])(vl|vision|visual|omni)($|[/_.:-])");
    private static final Pattern REASONING_PATTERN = Pattern.compile(
            "reasoning|reasoner|deepseek-r1|(^|[/_.:-])r1($|[/_.:-])"
                    + "|(^|[/_.:-])qwq($|[/_.:-])|(^|[/_.:-])o[134]($|[/_.:-])");

    /** 禁止实例化规则工具类。 */
    private ModelCapabilityNameRules() {
    }

    /**
     * 判断模型 ID 是否明确指向重排模型。
     *
     * @param modelId 模型 ID
     * @return 明确为重排模型返回 true
     */
    static boolean isRerankModel(String modelId) {
        return RERANK_PATTERN.matcher(normalize(modelId)).find();
    }

    /**
     * 判断模型 ID 是否明确指向嵌入模型。
     *
     * @param modelId 模型 ID
     * @return 明确为嵌入模型返回 true
     */
    static boolean isEmbeddingModel(String modelId) {
        return EMBEDDING_PATTERN.matcher(normalize(modelId)).find();
    }

    /**
     * 判断模型 ID 是否明确指向视觉模型。
     *
     * @param modelId 模型 ID
     * @return 明确支持视觉输入返回 true
     */
    static boolean supportsVision(String modelId) {
        return VISION_PATTERN.matcher(normalize(modelId)).find();
    }

    /**
     * 判断模型 ID 是否明确指向推理模型。
     *
     * @param modelId 模型 ID
     * @return 明确支持推理返回 true
     */
    static boolean supportsReasoning(String modelId) {
        return REASONING_PATTERN.matcher(normalize(modelId)).find();
    }

    /**
     * 规范化待匹配模型 ID。
     *
     * @param modelId 原始模型 ID
     * @return 规范化模型 ID
     */
    private static String normalize(String modelId) {
        return modelId == null ? "" : modelId.trim().toLowerCase(Locale.ROOT);
    }
}
