package tech.easyflow.ai.node;

import org.junit.Assert;
import org.junit.Test;
import tech.easyflow.common.web.exceptions.BusinessException;
import tech.easyflow.datacenter.execution.model.DatasetRef;

import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

public class SearchDatasetNodeTest {

    @Test
    public void testResolveQuerySqlShouldUseNodeQuerySqlAndResolveTemplate() throws Exception {
        DatasetRef datasetRef = new DatasetRef();
        datasetRef.setSourceId(BigInteger.valueOf(1001L));
        SearchDatasetNode node = new SearchDatasetNode(datasetRef, """
                SELECT id, name
                FROM orders_{{biz}}
                WHERE name LIKE '%{{keyword}}%'
                ORDER BY created_at {{direction}}
                """);

        Map<String, Object> params = new HashMap<>();
        params.put("biz", "prod");
        params.put("keyword", "vip");
        params.put("direction", "DESC");

        String sql = invokeResolveQuerySql(node, params);
        Assert.assertEquals("""
                SELECT id, name
                FROM orders_prod
                WHERE name LIKE '%vip%'
                ORDER BY created_at DESC
                """.trim(), sql);
    }

    @Test
    public void testResolveQuerySqlShouldUseNodeQuerySqlWhenParamsDoNotContainSql() throws Exception {
        DatasetRef datasetRef = new DatasetRef();
        datasetRef.setSourceId(BigInteger.valueOf(2002L));
        SearchDatasetNode node = new SearchDatasetNode(datasetRef, "SELECT * FROM fallback_table");

        Map<String, Object> params = new HashMap<>();

        String sql = invokeResolveQuerySql(node, params);
        Assert.assertEquals("SELECT * FROM fallback_table", sql);
    }

    @Test
    public void testResolveQuerySqlShouldRejectBlankSql() throws Exception {
        DatasetRef datasetRef = new DatasetRef();
        datasetRef.setSourceId(BigInteger.valueOf(3003L));
        SearchDatasetNode node = new SearchDatasetNode(datasetRef, "   ");

        try {
            invokeResolveQuerySql(node, new HashMap<>());
            Assert.fail("expected BusinessException");
        } catch (Exception e) {
            Throwable cause = e.getCause() == null ? e : e.getCause();
            Assert.assertTrue(cause instanceof BusinessException);
            Assert.assertEquals("查询数据节点未设置 SQL", cause.getMessage());
        }
    }

    private String invokeResolveQuerySql(SearchDatasetNode node, Map<String, Object> params) throws Exception {
        Method method = SearchDatasetNode.class.getDeclaredMethod("resolveQuerySql", Map.class);
        method.setAccessible(true);
        return (String) method.invoke(node, params);
    }
}
