package tech.easyflow.admin.controller.ai;

import jakarta.servlet.http.HttpServletRequest;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Locale;
import java.util.Map;

/**
 * {@link WorkflowShareController} 分享地址构建测试。
 */
public class WorkflowShareControllerTest {

    /**
     * 验证分享地址保留前端部署基路径。
     *
     * @throws Exception 反射调用失败时抛出
     */
    @Test
    public void shouldPreserveFrontendBasePathFromReferer() throws Exception {
        HttpServletRequest request = request(Map.of(
                "referer",
                "https://example.test/easyflow/ai/workflow?page=1"
        ));

        Assert.assertEquals(
                buildShareBaseUrl(request),
                "https://example.test/easyflow/share/workflow"
        );
    }

    /**
     * 验证反向代理头用于构建外部 HTTPS 分享地址。
     *
     * @throws Exception 反射调用失败时抛出
     */
    @Test
    public void shouldUseForwardedOriginAndPrefix() throws Exception {
        HttpServletRequest request = request(Map.of(
                "x-forwarded-proto", "https",
                "x-forwarded-host", "example.test",
                "x-forwarded-prefix", "/easyflow"
        ));

        Assert.assertEquals(
                buildShareBaseUrl(request),
                "https://example.test/easyflow/share/workflow"
        );
    }

    /**
     * 调用控制器的分享基础地址构建方法。
     *
     * @param request 模拟 HTTP 请求
     * @return 分享基础地址
     * @throws Exception 反射调用失败时抛出
     */
    private String buildShareBaseUrl(HttpServletRequest request) throws Exception {
        Method method = WorkflowShareController.class.getDeclaredMethod(
                "buildShareBaseUrl",
                HttpServletRequest.class
        );
        method.setAccessible(true);
        return (String) method.invoke(new WorkflowShareController(), request);
    }

    /**
     * 创建仅提供请求头能力的轻量 Servlet 请求代理。
     *
     * @param headers 小写请求头映射
     * @return HTTP 请求代理
     */
    private HttpServletRequest request(Map<String, String> headers) {
        return (HttpServletRequest) Proxy.newProxyInstance(
                getClass().getClassLoader(),
                new Class<?>[]{HttpServletRequest.class},
                (proxy, method, args) -> {
                    if ("getHeader".equals(method.getName())) {
                        String name = String.valueOf(args[0]).toLowerCase(Locale.ROOT);
                        return headers.get(name);
                    }
                    return defaultValue(method.getReturnType());
                }
        );
    }

    /**
     * 返回代理方法所需的基础类型默认值。
     *
     * @param returnType 返回值类型
     * @return 对应默认值
     */
    private Object defaultValue(Class<?> returnType) {
        if (!returnType.isPrimitive()) {
            return null;
        }
        if (boolean.class == returnType) {
            return false;
        }
        if (char.class == returnType) {
            return '\0';
        }
        if (byte.class == returnType) {
            return (byte) 0;
        }
        if (short.class == returnType) {
            return (short) 0;
        }
        if (int.class == returnType) {
            return 0;
        }
        if (long.class == returnType) {
            return 0L;
        }
        if (float.class == returnType) {
            return 0F;
        }
        return 0D;
    }
}
