package tech.easyflow.usercenter.controller.agent;

import com.mybatisflex.core.query.QueryWrapper;
import org.testng.Assert;
import org.testng.annotations.Test;
import tech.easyflow.agent.entity.Agent;
import tech.easyflow.agent.security.AgentVisibilityQueryHelper;
import tech.easyflow.agent.service.AgentService;
import tech.easyflow.common.entity.LoginAccount;
import tech.easyflow.usercenter.model.agent.UcAgentListItemVo;

import java.lang.reflect.Proxy;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;

/**
 * {@link UcAgentController} 用户端 Agent 可见性测试。
 */
public class UcAgentControllerTest {

    /**
     * 验证列表把可见性限制下推到查询，并仅返回发布快照的展示字段。
     */
    @Test
    public void listShouldFilterVisibilityAndReturnPublishedSummary() {
        Agent visibleAgent = liveAgent(BigInteger.ONE, "草稿名称一", "发布名称一");
        AgentService agentService = proxy(
                AgentService.class,
                (instance, method, args) -> {
                    if ("list".equals(method.getName())) {
                        return List.of(visibleAgent);
                    }
                    if ("fromSnapshot".equals(method.getName())) {
                        Map<?, ?> snapshot = (Map<?, ?>) args[0];
                        Agent published = new Agent();
                        published.setName(String.valueOf(snapshot.get("name")));
                        published.setDescription(String.valueOf(snapshot.get("description")));
                        published.setAvatar(String.valueOf(snapshot.get("avatar")));
                        return published;
                    }
                    throw new AssertionError("测试路径不应调用 AgentService." + method.getName());
                }
        );
        RecordingVisibilityQueryHelper visibilityQueryHelper = new RecordingVisibilityQueryHelper();
        LoginAccount account = new LoginAccount();
        account.setTenantId(BigInteger.ONE);
        UcAgentController controller = new TestUcAgentController(
                agentService,
                visibilityQueryHelper,
                account
        );

        List<UcAgentListItemVo> result = controller.list().getData();

        Assert.assertEquals(1, result.size());
        Assert.assertEquals(visibleAgent.getId(), result.get(0).getId());
        Assert.assertEquals("发布名称一", result.get(0).getName());
        Assert.assertEquals("发布描述一", result.get(0).getDescription());
        Assert.assertEquals("avatar-一", result.get(0).getAvatar());
        Assert.assertTrue(visibilityQueryHelper.applied);
    }

    /**
     * 创建带草稿字段和发布快照的 Agent。
     *
     * @param id Agent ID
     * @param draftName 草稿名称
     * @param publishedName 发布名称
     * @return Agent
     */
    private Agent liveAgent(BigInteger id, String draftName, String publishedName) {
        Agent agent = new Agent();
        agent.setId(id);
        agent.setName(draftName);
        String suffix = BigInteger.ONE.equals(id) ? "一" : "二";
        agent.setPublishedSnapshotJson(Map.of(
                "name", publishedName,
                "description", "发布描述" + suffix,
                "avatar", "avatar-" + suffix
        ));
        return agent;
    }

    /**
     * 创建接口代理。
     *
     * @param type 接口类型
     * @param handler 调用处理器
     * @param <T> 接口类型
     * @return 代理实例
     */
    private <T> T proxy(Class<T> type, java.lang.reflect.InvocationHandler handler) {
        return type.cast(Proxy.newProxyInstance(type.getClassLoader(), new Class<?>[]{type}, handler));
    }

    /**
     * 记录可见性条件是否已下推到查询。
     */
    private static final class RecordingVisibilityQueryHelper extends AgentVisibilityQueryHelper {

        private boolean applied;

        /**
         * 创建记录型可见性查询助手。
         */
        private RecordingVisibilityQueryHelper() {
            super(null, null);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void applyReadableAccess(QueryWrapper queryWrapper) {
            applied = true;
        }
    }

    /**
     * 使用固定登录账号的用户中心 Agent 控制器。
     */
    private static final class TestUcAgentController extends UcAgentController {

        private final LoginAccount account;

        /**
         * 创建测试控制器。
         *
         * @param agentService Agent 服务
         * @param visibilityQueryHelper 可见性查询助手
         * @param account 当前账号
         */
        private TestUcAgentController(AgentService agentService,
                                      AgentVisibilityQueryHelper visibilityQueryHelper,
                                      LoginAccount account) {
            super(agentService, visibilityQueryHelper);
            this.account = account;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        protected LoginAccount requireCurrentAccount() {
            return account;
        }
    }
}
