package tech.easyflow.skill.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import tech.easyflow.ai.enums.PublishStatus;
import tech.easyflow.skill.entity.Skill;
import tech.easyflow.skill.entity.SkillToolBinding;
import tech.easyflow.skill.service.SkillService;
import tech.easyflow.skill.service.SkillToolBindingService;

import java.math.BigInteger;
import java.util.List;
import java.util.Map;

/**
 * Skill 对平台 Tool 的生命周期引用查询测试。
 */
public class SkillToolReferenceProviderImplTest {

    /**
     * 草稿绑定和有效发布快照都应参与 Workflow 下线与删除影响检查。
     */
    @Test
    public void shouldIncludeDraftAndPublishedWorkflowReferences() {
        SkillService skillService = Mockito.mock(SkillService.class);
        SkillToolBindingService bindingService = Mockito.mock(SkillToolBindingService.class);
        SkillToolBinding draftBinding = new SkillToolBinding();
        draftBinding.setSkillId(BigInteger.ONE);
        draftBinding.setToolType("WORKFLOW");
        draftBinding.setTargetId(BigInteger.TEN);
        Skill publishedProjection = skill(BigInteger.TWO, "线上 Skill");
        publishedProjection.setPublishStatus(PublishStatus.PUBLISHED.getCode());
        publishedProjection.setPublishedToolBindingsJson(Map.of(
                "bindings", List.of(Map.of(
                        "toolType", "WORKFLOW",
                        "targetId", BigInteger.TEN))));
        Mockito.when(bindingService.list(Mockito.any(QueryWrapper.class)))
                .thenReturn(List.of(draftBinding));
        Mockito.when(skillService.list(Mockito.any(QueryWrapper.class)))
                .thenReturn(List.of(publishedProjection));
        Mockito.when(skillService.listByIds(Mockito.anyCollection()))
                .thenReturn(List.of(
                        skill(BigInteger.ONE, "草稿 Skill"),
                        skill(BigInteger.TWO, "线上 Skill")));
        SkillToolReferenceProviderImpl provider = new SkillToolReferenceProviderImpl(
                skillService, bindingService);

        var references = provider.listSkillsByWorkflowId(BigInteger.TEN);

        Assert.assertEquals(2, references.size());
        Assert.assertEquals("Skill“草稿 Skill”", references.get(0).getTitle());
        Assert.assertEquals("Skill“线上 Skill”", references.get(1).getTitle());
    }

    /**
     * 已下线发布快照不应继续阻止 Tool 生命周期操作。
     */
    @Test
    public void shouldIgnoreOfflinePublishedSnapshot() {
        SkillService skillService = Mockito.mock(SkillService.class);
        SkillToolBindingService bindingService = Mockito.mock(SkillToolBindingService.class);
        Skill offline = skill(BigInteger.ONE, "已下线 Skill");
        offline.setPublishStatus(PublishStatus.OFFLINE.getCode());
        offline.setPublishedToolBindingsJson(Map.of(
                "bindings", List.of(Map.of(
                        "toolType", "MCP",
                        "targetId", BigInteger.TEN))));
        Mockito.when(bindingService.list(Mockito.any(QueryWrapper.class))).thenReturn(List.of());
        Mockito.when(skillService.list(Mockito.any(QueryWrapper.class))).thenReturn(List.of(offline));
        SkillToolReferenceProviderImpl provider = new SkillToolReferenceProviderImpl(
                skillService, bindingService);

        Assert.assertTrue(provider.listSkillsByMcpId(BigInteger.TEN).isEmpty());
    }

    /**
     * 创建 Skill 摘要。
     *
     * @param id Skill ID
     * @param displayName 展示名
     * @return Skill
     */
    private Skill skill(BigInteger id, String displayName) {
        Skill skill = new Skill();
        skill.setId(id);
        skill.setName("skill-" + id);
        skill.setDisplayName(displayName);
        return skill;
    }
}
