package tech.easyflow.skill.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.stereotype.Component;
import tech.easyflow.ai.enums.PublishStatus;
import tech.easyflow.ai.service.SkillToolReferenceProvider;
import tech.easyflow.ai.vo.OfflineImpactBindingVo;
import tech.easyflow.skill.entity.Skill;
import tech.easyflow.skill.entity.SkillToolBinding;
import tech.easyflow.skill.enums.SkillToolType;
import tech.easyflow.skill.service.SkillService;
import tech.easyflow.skill.service.SkillToolBindingService;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Skill 草稿与有效发布快照中的平台 Tool 引用提供者。
 */
@Component
public class SkillToolReferenceProviderImpl implements SkillToolReferenceProvider {

    private final SkillService skillService;
    private final SkillToolBindingService bindingService;

    /**
     * 创建 Skill Tool 引用提供者。
     *
     * @param skillService Skill 服务
     * @param bindingService Skill Tool 绑定服务
     */
    public SkillToolReferenceProviderImpl(SkillService skillService,
                                          SkillToolBindingService bindingService) {
        this.skillService = skillService;
        this.bindingService = bindingService;
    }

    /** {@inheritDoc} */
    @Override public List<OfflineImpactBindingVo> listSkillsByWorkflowId(BigInteger id) {
        return listReferences(SkillToolType.WORKFLOW, id);
    }

    /** {@inheritDoc} */
    @Override public List<OfflineImpactBindingVo> listSkillsByPluginItemId(BigInteger id) {
        return listReferences(SkillToolType.PLUGIN, id);
    }

    /** {@inheritDoc} */
    @Override public List<OfflineImpactBindingVo> listSkillsByMcpId(BigInteger id) {
        return listReferences(SkillToolType.MCP, id);
    }

    private List<OfflineImpactBindingVo> listReferences(SkillToolType type, BigInteger targetId) {
        Set<BigInteger> ids = new LinkedHashSet<>();
        for (SkillToolBinding binding : bindingService.list(QueryWrapper.create()
                .eq(SkillToolBinding::getToolType, type.name())
                .eq(SkillToolBinding::getTargetId, targetId))) {
            ids.add(binding.getSkillId());
        }
        for (Skill skill : skillService.list(QueryWrapper.create()
                .select(Skill::getId, Skill::getPublishStatus, Skill::getPublishedToolBindingsJson)
                .isNotNull(Skill::getPublishedToolBindingsJson))) {
            if (PublishStatus.from(skill.getPublishStatus()).isExternallyVisible()
                    && contains(skill.getPublishedToolBindingsJson(), type, targetId)) {
                ids.add(skill.getId());
            }
        }
        List<OfflineImpactBindingVo> result = new ArrayList<>();
        for (Skill skill : skillService.listByIds(ids)) {
            OfflineImpactBindingVo item = new OfflineImpactBindingVo();
            item.setId(skill.getId());
            item.setTitle("Skill“" + (skill.getDisplayName() == null ? skill.getName() : skill.getDisplayName()) + "”");
            result.add(item);
        }
        return result;
    }

    private boolean contains(Map<String, Object> snapshot, SkillToolType type, BigInteger targetId) {
        Object raw = snapshot == null ? null : snapshot.get("bindings");
        if (!(raw instanceof List<?> bindings)) {
            return false;
        }
        return bindings.stream().anyMatch(item -> item instanceof Map<?, ?> binding
                && type.name().equalsIgnoreCase(String.valueOf(binding.get("toolType")))
                && targetId.toString().equals(String.valueOf(binding.get("targetId"))));
    }
}
