package tech.easyflow.datacenter.connector.support;

import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import tech.easyflow.datacenter.entity.DatacenterTable;
import tech.easyflow.datacenter.execution.model.DatacenterQueryRequest;
import tech.easyflow.datacenter.meta.enums.DatacenterSourceType;

import java.math.BigInteger;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

/**
 * {@link AbstractInternalTableConnector} 内部查询结果规范化测试。
 */
public class AbstractInternalTableConnectorTest {

    /**
     * 验证 JDBC 返回的大写列标签会转换为数据集字段使用的小写名称。
     */
    @Test
    public void shouldNormalizeMysqlColumnLabelsToLowerCase() {
        Row row = new Row();
        row.put("COL_ID", "deepseek-v4-pro");
        row.put("TOKEN", BigInteger.valueOf(3));

        AbstractInternalTableConnector.normalizeRows(List.of(row));

        Assert.assertEquals(
                List.of("col_id", "token"),
                List.copyOf(row.keySet()));
        Assert.assertEquals("deepseek-v4-pro", row.get("col_id"));
        Assert.assertEquals("3", row.get("token"));
    }

    /**
     * 验证统计查询修改投影后，不会污染后续的分页查询包装器。
     */
    @Test
    public void shouldUseIndependentQueryWrapperForPaginationAfterCount() {
        DatacenterTable table = new DatacenterTable();
        table.setActualTable("preview_table");
        DatacenterQueryRequest request = new DatacenterQueryRequest();
        request.setPageNumber(1L);
        request.setPageSize(10L);

        Row record = new Row();
        record.put("MODEL_ID", "deepseek-v4-pro");
        AtomicReference<QueryWrapper> countWrapper = new AtomicReference<>();
        AtomicReference<QueryWrapper> pageWrapper = new AtomicReference<>();
        try (MockedStatic<Db> db = Mockito.mockStatic(Db.class)) {
            db.when(() -> Db.selectCountByQuery(
                            Mockito.eq("preview_table"),
                            Mockito.any(QueryWrapper.class)))
                    .thenAnswer(invocation -> {
                        QueryWrapper wrapper = invocation.getArgument(1);
                        countWrapper.set(wrapper);
                        // 模拟 MyBatis-Flex 为 count 查询自动追加 COUNT(*) 投影的行为。
                        wrapper.select("COUNT(*)");
                        return 1L;
                    });
            db.when(() -> Db.paginate(
                            Mockito.eq("preview_table"),
                            Mockito.any(Page.class),
                            Mockito.any(QueryWrapper.class)))
                    .thenAnswer(invocation -> {
                        pageWrapper.set(invocation.getArgument(2));
                        return new Page<>(List.of(record), 1L, 10L, 1L);
                    });

            Page<Row> page = new TestInternalTableConnector().queryPage(
                    null, table, request);

            Assert.assertNotSame(countWrapper.get(), pageWrapper.get());
            Assert.assertEquals("deepseek-v4-pro", page.getRecords().get(0).get("model_id"));
        }
    }

    /**
     * 供内部动态表查询测试使用的最小连接器实现。
     */
    private static class TestInternalTableConnector extends AbstractInternalTableConnector {

        /**
         * 创建测试连接器。
         */
        private TestInternalTableConnector() {
            super(DatacenterSourceType.EXCEL, Set.of(), null);
        }
    }
}
