package tech.easyflow.admin.controller.agent;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.testng.Assert;
import org.testng.annotations.Test;
import tech.easyflow.common.domain.Result;
import tech.easyflow.common.web.jsonbody.JsonBody;
import tech.easyflow.common.web.jsonbody.JsonBodyParser;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;

/**
 * Agent Skill 绑定管理端 API 安全契约测试。
 */
public class AgentSkillBindingContractTest {

    /**
     * 验证请求 DTO 仅暴露 Agent ID、Skill ID 与排序号。
     *
     * @throws Exception 反序列化失败
     */
    @Test
    public void requestUsesWhitelistFieldsAndDropsServerSnapshot() throws Exception {
        JSONObject json = JSON.parseObject("""
                {
                  "agentId": 10,
                  "bindings": [{
                    "skillId": 101,
                    "sortNo": 2,
                    "resourceSnapshot": {"skillContent": "forged"},
                    "resourceSummary": {"displayName": "forged"}
                  }]
                }
                """);

        AgentSkillBindingUpdateRequest request = (AgentSkillBindingUpdateRequest) JsonBodyParser.parseJsonBody(
                json, AgentSkillBindingUpdateRequest.class, AgentSkillBindingUpdateRequest.class, "");

        Assert.assertEquals(request.getAgentId(), BigInteger.TEN);
        Assert.assertEquals(request.getBindings().get(0).getSkillId(), BigInteger.valueOf(101));
        Assert.assertEquals(request.getBindings().get(0).getSortNo(), Integer.valueOf(2));
        Assert.assertTrue(request.getBindings().get(0).toEntity().getResourceSnapshot().isEmpty());
        Assert.assertTrue(request.getBindings().get(0).toEntity().getResourceSummary().isEmpty());
        Assert.assertEquals(
                Arrays.stream(AgentSkillBindingUpdateRequest.Binding.class.getDeclaredFields())
                        .filter(field -> !Modifier.isStatic(field.getModifiers()))
                        .map(field -> field.getName()).toList(),
                List.of("skillId", "sortNo"));
    }

    /**
     * 验证更新入口使用白名单 DTO 并返回脱敏视图。
     *
     * @throws Exception 反射失败
     */
    @Test
    public void updateEndpointReturnsSafeSkillBindingViews() throws Exception {
        Method method = AgentController.class.getMethod(
                "updateSkillBinding", AgentSkillBindingUpdateRequest.class);
        JsonBody jsonBody = method.getParameters()[0].getAnnotation(JsonBody.class);
        ParameterizedType resultType = (ParameterizedType) method.getGenericReturnType();
        ParameterizedType listType = (ParameterizedType) resultType.getActualTypeArguments()[0];

        Assert.assertNotNull(jsonBody);
        Assert.assertEquals(resultType.getRawType(), Result.class);
        Assert.assertEquals(listType.getRawType(), List.class);
        Assert.assertEquals(listType.getActualTypeArguments()[0], AgentDetailView.SkillBindingView.class);
        Assert.assertFalse(Arrays.stream(AgentDetailView.SkillBindingView.class.getRecordComponents())
                .anyMatch(component -> "resourceSnapshot".equals(component.getName())));
    }
}
