package tech.easyflow.ai.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import org.junit.Assert;
import org.junit.Test;
import tech.easyflow.ai.entity.DocumentCollection;
import tech.easyflow.ai.entity.Workflow;
import tech.easyflow.ai.plugin.workflow.dependency.WorkflowPluginDependencyService;
import tech.easyflow.ai.service.AgentResourceReferenceService;
import tech.easyflow.ai.service.DocumentCollectionService;
import tech.easyflow.ai.service.WorkflowService;
import tech.easyflow.ai.vo.OfflineImpactBindingVo;
import tech.easyflow.ai.vo.OfflineImpactCheckVo;
import tech.easyflow.common.web.exceptions.BusinessException;

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

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
 * Agent 资源下线影响检查测试。
 */
public class ResourceOfflineImpactServiceImplTest {

    /**
     * 验证工作流影响结果使用 Agent 绑定字段并委托 Agent 解绑。
     */
    @Test
    public void shouldReportAndUnbindAgentWorkflowBindings() {
        WorkflowService workflowService = mock(WorkflowService.class);
        DocumentCollectionService documentCollectionService =
                mock(DocumentCollectionService.class);
        WorkflowPluginDependencyService pluginDependencyService =
                mock(WorkflowPluginDependencyService.class);
        AgentResourceReferenceService referenceService = mock(AgentResourceReferenceService.class);
        BigInteger workflowId = BigInteger.valueOf(10);
        OfflineImpactBindingVo binding = binding(BigInteger.ONE, "测试智能体");
        when(referenceService.listAgentsByWorkflowId(workflowId)).thenReturn(List.of(binding));
        when(pluginDependencyService.listPluginsByWorkflowId(workflowId))
                .thenReturn(Collections.emptyList());
        ResourceOfflineImpactServiceImpl service = new ResourceOfflineImpactServiceImpl(
                workflowService, documentCollectionService, pluginDependencyService, referenceService);

        OfflineImpactCheckVo result = service.checkWorkflowImpact(workflowId);
        service.unbindWorkflowFromAgents(workflowId);

        Assert.assertTrue(result.isHasAgentBindings());
        Assert.assertEquals(List.of(binding), result.getAgentBindings());
        Assert.assertTrue(result.getMessage().contains("智能体"));
        verify(referenceService).unbindWorkflow(workflowId);
    }

    /**
     * 验证知识库影响结果使用 Agent 绑定字段并委托 Agent 解绑。
     */
    @Test
    public void shouldReportAndUnbindAgentKnowledgeBindings() {
        WorkflowService workflowService = mock(WorkflowService.class);
        DocumentCollectionService documentCollectionService =
                mock(DocumentCollectionService.class);
        WorkflowPluginDependencyService pluginDependencyService =
                mock(WorkflowPluginDependencyService.class);
        AgentResourceReferenceService referenceService = mock(AgentResourceReferenceService.class);
        BigInteger knowledgeId = BigInteger.valueOf(20);
        OfflineImpactBindingVo binding = binding(BigInteger.TWO, "知识智能体");
        DocumentCollection knowledge = new DocumentCollection();
        knowledge.setTenantId(BigInteger.ONE);
        when(documentCollectionService.getById(knowledgeId)).thenReturn(knowledge);
        when(referenceService.listAgentsByKnowledgeId(knowledgeId)).thenReturn(List.of(binding));
        when(workflowService.list(any(QueryWrapper.class))).thenReturn(Collections.emptyList());
        ResourceOfflineImpactServiceImpl service = new ResourceOfflineImpactServiceImpl(
                workflowService, documentCollectionService, pluginDependencyService, referenceService);

        OfflineImpactCheckVo result = service.checkKnowledgeImpact(knowledgeId);
        service.unbindKnowledgeFromAgents(knowledgeId);

        Assert.assertTrue(result.isHasAgentBindings());
        Assert.assertEquals(List.of(binding), result.getAgentBindings());
        Assert.assertTrue(result.getMessage().contains("智能体"));
        verify(referenceService).unbindKnowledge(knowledgeId);
    }

    /**
     * 工作流定义损坏时必须阻止知识库下线，避免漏判引用关系。
     */
    @Test(expected = BusinessException.class)
    public void shouldFailClosedWhenWorkflowContentIsInvalid() {
        WorkflowService workflowService = mock(WorkflowService.class);
        DocumentCollectionService documentCollectionService =
                mock(DocumentCollectionService.class);
        WorkflowPluginDependencyService pluginDependencyService =
                mock(WorkflowPluginDependencyService.class);
        AgentResourceReferenceService referenceService = mock(AgentResourceReferenceService.class);
        BigInteger knowledgeId = BigInteger.valueOf(20);
        DocumentCollection knowledge = new DocumentCollection();
        knowledge.setTenantId(BigInteger.ONE);
        Workflow workflow = new Workflow();
        workflow.setId(BigInteger.TEN);
        workflow.setContent("{invalid");
        when(documentCollectionService.getById(knowledgeId)).thenReturn(knowledge);
        when(referenceService.listAgentsByKnowledgeId(knowledgeId))
                .thenReturn(Collections.emptyList());
        when(workflowService.list(any(QueryWrapper.class))).thenReturn(List.of(workflow));
        ResourceOfflineImpactServiceImpl service = new ResourceOfflineImpactServiceImpl(
                workflowService, documentCollectionService, pluginDependencyService, referenceService);

        service.checkKnowledgeImpact(knowledgeId);
    }

    /**
     * 创建绑定摘要。
     *
     * @param id 资源 ID
     * @param title 标题
     * @return 绑定摘要
     */
    private OfflineImpactBindingVo binding(BigInteger id, String title) {
        OfflineImpactBindingVo binding = new OfflineImpactBindingVo();
        binding.setId(id);
        binding.setTitle(title);
        return binding;
    }
}
