package tech.easyflow.agent.service.impl;

import tech.easyflow.agent.entity.AgentKnowledgeBinding;
import tech.easyflow.agent.entity.AgentSkillBinding;
import tech.easyflow.agent.entity.AgentToolBinding;
import tech.easyflow.agent.enums.AgentToolType;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 比较 Agent 绑定的可持久化业务字段，忽略 ID、审计字段与展示摘要。
 */
final class AgentBindingSemanticComparator {

    private static final String DEFAULT_RETRIEVAL_MODE = "HYBRID";

    private AgentBindingSemanticComparator() {
    }

    /**
     * 判断工具绑定整组替换是否会产生业务变化。
     *
     * @param current 当前持久化绑定
     * @param requested 客户端请求绑定
     * @return 业务字段完全一致时返回 {@code true}
     */
    static boolean sameTools(List<AgentToolBinding> current, List<AgentToolBinding> requested) {
        List<AgentToolBinding> left = safeList(current);
        List<AgentToolBinding> right = safeList(requested);
        if (left.size() != right.size()) {
            return false;
        }
        for (int index = 0; index < left.size(); index++) {
            AgentToolBinding persisted = left.get(index);
            AgentToolBinding incoming = right.get(index);
            if (persisted == null || incoming == null
                    || !Objects.equals(normalizeToolType(persisted.getToolType()), normalizeToolType(incoming.getToolType()))
                    || !Objects.equals(persisted.getTargetId(), incoming.getTargetId())
                    || !Objects.equals(text(persisted.getToolName()), text(incoming.getToolName()))
                    || !Objects.equals(enabled(persisted.getEnabled()), enabled(incoming.getEnabled()))
                    || !Objects.equals(Boolean.TRUE.equals(persisted.getHitlEnabled()),
                    Boolean.TRUE.equals(incoming.getHitlEnabled()))
                    || !Objects.equals(map(persisted.getHitlConfigJson()), map(incoming.getHitlConfigJson()))
                    || !Objects.equals(map(persisted.getOptionsJson()), map(incoming.getOptionsJson()))
                    || !Objects.equals(persisted.getSortNo(), sortNo(incoming.getSortNo(), index))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断知识库绑定整组替换是否会产生业务变化。
     *
     * @param current 当前持久化绑定
     * @param requested 客户端请求绑定
     * @return 业务字段完全一致时返回 {@code true}
     */
    static boolean sameKnowledges(List<AgentKnowledgeBinding> current,
                                  List<AgentKnowledgeBinding> requested) {
        List<AgentKnowledgeBinding> left = safeList(current);
        List<AgentKnowledgeBinding> right = safeList(requested);
        if (left.size() != right.size()) {
            return false;
        }
        for (int index = 0; index < left.size(); index++) {
            AgentKnowledgeBinding persisted = left.get(index);
            AgentKnowledgeBinding incoming = right.get(index);
            if (persisted == null || incoming == null
                    || !Objects.equals(persisted.getKnowledgeId(), incoming.getKnowledgeId())
                    || !Objects.equals(retrievalMode(persisted.getRetrievalMode()),
                    retrievalMode(incoming.getRetrievalMode()))
                    || !Objects.equals(enabled(persisted.getEnabled()), enabled(incoming.getEnabled()))
                    || !Objects.equals(map(persisted.getOptionsJson()), map(incoming.getOptionsJson()))
                    || !Objects.equals(persisted.getSortNo(), sortNo(incoming.getSortNo(), index))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断 Skill 绑定顺序是否发生变化。
     *
     * @param current 当前持久化绑定
     * @param requested 客户端请求绑定
     * @return Skill ID 与稳定顺序完全一致时返回 {@code true}
     */
    static boolean sameSkills(List<AgentSkillBinding> current, List<AgentSkillBinding> requested) {
        List<AgentSkillBinding> left = safeList(current);
        List<AgentSkillBinding> right = safeList(requested);
        if (left.size() != right.size()) {
            return false;
        }
        for (int index = 0; index < left.size(); index++) {
            AgentSkillBinding persisted = left.get(index);
            AgentSkillBinding incoming = right.get(index);
            if (persisted == null || incoming == null
                    || !Objects.equals(persisted.getSkillId(), incoming.getSkillId())
                    || !Objects.equals(persisted.getSortNo(), index)) {
                return false;
            }
        }
        return true;
    }

    private static String normalizeToolType(String value) {
        try {
            return AgentToolType.from(value).name();
        } catch (RuntimeException ignored) {
            return value;
        }
    }

    private static String retrievalMode(String value) {
        return value == null || value.isBlank()
                ? DEFAULT_RETRIEVAL_MODE : value.trim().toUpperCase(java.util.Locale.ROOT);
    }

    private static String text(String value) {
        return value == null ? "" : value;
    }

    private static Boolean enabled(Boolean value) {
        return value == null || value;
    }

    private static Integer sortNo(Integer value, int index) {
        return value == null ? index : value;
    }

    private static Map<String, Object> map(Map<String, Object> value) {
        return value == null ? Collections.emptyMap() : value;
    }

    private static <T> List<T> safeList(List<T> value) {
        return value == null ? Collections.emptyList() : value;
    }
}
