package tech.easyflow.ai.easyagentsflow.repository;

import com.easyagents.flow.core.chain.ChainDefinition;
import com.easyagents.flow.core.node.ConfirmNode;
import com.easyagents.flow.core.parser.ChainParser;
import org.junit.Assert;
import org.junit.Test;
import tech.easyflow.ai.easyagentsflow.service.WorkflowDatacenterContentService;
import tech.easyflow.ai.entity.Workflow;
import tech.easyflow.ai.node.WorkflowNode;
import tech.easyflow.common.web.exceptions.BusinessException;

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

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 * Agent Workflow 冻结快照兼容性测试。
 */
public class AgentWorkflowSnapshotFactoryTest {

    /**
     * 验证快照只保留 Runtime 白名单字段并使用准备后的内容。
     */
    @Test
    public void shouldBuildWhitelistedSnapshotFromPreparedContent() {
        ChainDefinition definition = new ChainDefinition();
        Workflow workflow = workflow();
        AgentWorkflowSnapshotFactory factory = factory(definition);

        Map<String, Object> snapshot = factory.snapshot(workflow);

        Assert.assertEquals(workflow.getId(), snapshot.get("id"));
        Assert.assertEquals("prepared-content", snapshot.get("content"));
        Assert.assertEquals(6, snapshot.size());
        Assert.assertFalse(snapshot.containsKey("tenantId"));
        Assert.assertFalse(snapshot.containsKey("publishedSnapshotJson"));
    }

    /**
     * 验证 Skill 或 Agent 发布投影会提前拒绝子工作流节点。
     */
    @Test
    public void shouldRejectSubWorkflowNode() {
        ChainDefinition definition = new ChainDefinition();
        definition.addNode(new WorkflowNode());

        assertConflict(factory(definition), "子工作流节点");
    }

    /**
     * 验证 Skill 或 Agent 发布投影会提前拒绝内部确认节点。
     */
    @Test
    public void shouldRejectConfirmNode() {
        ChainDefinition definition = new ChainDefinition();
        definition.addNode(new ConfirmNode());

        assertConflict(factory(definition), "内部确认节点");
    }

    private AgentWorkflowSnapshotFactory factory(ChainDefinition definition) {
        ChainParser parser = mock(ChainParser.class);
        WorkflowDatacenterContentService contentService = mock(WorkflowDatacenterContentService.class);
        when(contentService.prepareContent("raw-content")).thenReturn("prepared-content");
        when(parser.parse("prepared-content")).thenReturn(definition);
        return new AgentWorkflowSnapshotFactory(parser, contentService);
    }

    private Workflow workflow() {
        Workflow workflow = new Workflow();
        workflow.setId(BigInteger.ONE);
        workflow.setTitle("合同审查");
        workflow.setDescription("审查合同风险");
        workflow.setEnglishName("contract_review");
        workflow.setRevision(3);
        workflow.setContent("raw-content");
        workflow.setTenantId(BigInteger.TEN);
        workflow.setPublishedSnapshotJson(Map.of("secret", "hidden"));
        return workflow;
    }

    private void assertConflict(AgentWorkflowSnapshotFactory factory, String message) {
        try {
            factory.snapshot(workflow());
            Assert.fail("Expected incompatible workflow to be rejected");
        } catch (BusinessException exception) {
            Assert.assertEquals(409, exception.getHttpStatus());
            Assert.assertTrue(exception.getMessage(), exception.getMessage().contains(message));
        }
    }
}
