package tech.easyflow.ai.service.impl;

import org.springframework.stereotype.Service;
import tech.easyflow.ai.service.AgentResourceBindingProvider;
import tech.easyflow.ai.service.AgentResourceReferenceService;
import tech.easyflow.ai.vo.OfflineImpactBindingVo;
import tech.easyflow.common.web.exceptions.BusinessException;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * Agent 资源引用查询服务实现。
 */
@Service
public class AgentResourceReferenceServiceImpl implements AgentResourceReferenceService {

    private final List<AgentResourceBindingProvider> providers;

    /**
     * 创建 Agent 资源引用查询服务。
     *
     * @param providers Agent 资源绑定提供者
     */
    public AgentResourceReferenceServiceImpl(List<AgentResourceBindingProvider> providers) {
        this.providers = providers == null ? List.of() : List.copyOf(providers);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<OfflineImpactBindingVo> listAgentsByWorkflowId(BigInteger workflowId) {
        return merge(provider -> provider.listAgentsByWorkflowId(workflowId));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<OfflineImpactBindingVo> listAgentsByKnowledgeId(BigInteger knowledgeId) {
        return merge(provider -> provider.listAgentsByKnowledgeId(knowledgeId));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void assertPluginItemsUnused(Collection<BigInteger> pluginItemIds) {
        if (pluginItemIds == null || pluginItemIds.isEmpty()) {
            return;
        }
        for (BigInteger pluginItemId : pluginItemIds) {
            assertUnused(
                    merge(provider -> provider.listAgentsByPluginItemId(pluginItemId)),
                    "插件工具"
            );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void assertMcpUnused(BigInteger mcpId) {
        assertUnused(merge(provider -> provider.listAgentsByMcpId(mcpId)), "MCP");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void assertModelsUnused(Collection<BigInteger> modelIds) {
        if (modelIds == null || modelIds.isEmpty()) {
            return;
        }
        for (BigInteger modelId : modelIds) {
            assertUnused(merge(provider -> provider.listAgentsByModelId(modelId)), "模型");
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void unbindWorkflow(BigInteger workflowId) {
        for (AgentResourceBindingProvider provider : requireProviders()) {
            provider.unbindWorkflow(workflowId);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void unbindKnowledge(BigInteger knowledgeId) {
        for (AgentResourceBindingProvider provider : requireProviders()) {
            provider.unbindKnowledge(knowledgeId);
        }
    }

    /**
     * 汇总所有提供者返回的 Agent 摘要。
     *
     * @param loader 单个提供者查询函数
     * @return 按 Agent ID 去重后的摘要
     */
    private List<OfflineImpactBindingVo> merge(
            Function<AgentResourceBindingProvider, List<OfflineImpactBindingVo>> loader) {
        Map<BigInteger, OfflineImpactBindingVo> merged = new LinkedHashMap<>();
        for (AgentResourceBindingProvider provider : requireProviders()) {
            List<OfflineImpactBindingVo> bindings = loader.apply(provider);
            if (bindings == null) {
                continue;
            }
            for (OfflineImpactBindingVo binding : bindings) {
                if (binding != null && binding.getId() != null) {
                    merged.putIfAbsent(binding.getId(), binding);
                }
            }
        }
        return new ArrayList<>(merged.values());
    }

    /**
     * 校验资源未被任何 Agent 引用。
     *
     * @param bindings Agent 引用摘要
     * @param resourceLabel 资源名称
     */
    private void assertUnused(List<OfflineImpactBindingVo> bindings, String resourceLabel) {
        if (bindings == null || bindings.isEmpty()) {
            return;
        }
        String agentTitle = bindings.get(0).getTitle();
        throw new BusinessException(
                resourceLabel + "仍被智能体“" + (agentTitle == null ? "未命名智能体" : agentTitle)
                        + "”使用，请先取消绑定或重新发布智能体后再删除"
        );
    }

    /**
     * 获取已注册提供者；缺失时阻止破坏性资源操作。
     *
     * @return Agent 资源绑定提供者
     */
    private List<AgentResourceBindingProvider> requireProviders() {
        if (providers.isEmpty()) {
            throw new BusinessException("Agent 资源引用检查服务不可用，请稍后重试");
        }
        return providers;
    }
}
