package org.example;

import org.example.Utils.ExceptionSummaryUtil;
import org.junit.jupiter.api.Test;

import java.nio.file.Files;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

class ExceptionSummaryUtilTest {

    @Test
    void summarizesDmInvalidTableErrorForClient() {
        RuntimeException exception = new RuntimeException("invoke failed",
                new RuntimeException("""
                        org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback;
                        bad SQL grammar []; nested exception is dm.jdbc.driver.DMException: 第53 行附近出现错误:
                        无效的表或视图名[MRP_CalcMaterialsumListTab]
                        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:476)
                        ... 103 common frames omitted
                        """));

        String summary = ExceptionSummaryUtil.summarizeForClient(exception);

        assertEquals("无效的表或视图[MRP_CalcMaterialsumListTab]", summary);
    }

    @Test
    void clientSummaryDoesNotExposeStackTraceNoise() {
        RuntimeException exception = new RuntimeException("wrapper",
                new RuntimeException("""
                        execute sql error:select * from demo,pms:[],mag:org.springframework.jdbc.BadSqlGrammarException
                        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:476)
                        Caused by: java.sql.SQLException: SQL语法错误: 缺少关键字
                        ... 103 common frames omitted
                        """));

        String summary = ExceptionSummaryUtil.summarizeForClient(exception);

        assertFalse(summary.contains("org.springframework"));
        assertFalse(summary.contains("JdbcTemplate"));
        assertFalse(summary.contains("StackTraceElement"));
        assertFalse(summary.contains("common frames omitted"));
        assertFalse(summary.contains("\tat "));
        assertTrue(summary.length() <= 300);
        assertTrue(summary.contains("SQL语法错误") || summary.contains("execute sql error"));
    }

    @Test
    void summarizesDeepDmMemberAccessErrorInsteadOfSpringSqlWrapper() {
        RuntimeException exception = new RuntimeException("java.lang.reflect.InvocationTargetException",
                new RuntimeException("""
                        org.springframework.dao.DataIntegrityViolationException: StatementCallback; SQL [SELECT
                        '订单MRP分析' as mps_lpt_sourcename,
                        itemno as mps_lpt_tm,
                        a.htids as mps_lpt_htids,
                        a.htnames as mps_lpt_htnames
                        from MRP_CalcMaterialsumListTab a
                        where charindex(','+cast(a.id as varchar)+',',',16921,')>0]; 第53 行附近出现错误:
                        无法解析的成员访问表达式[a.htids]
                        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:476)
                        ... 103 common frames omitted
                        Caused by: dm.jdbc.driver.DMException: 第53 行附近出现错误:
                        无法解析的成员访问表达式[a.htids]
                        at dm.jdbc.driver.DBError.throwException(SourceFile:793)
                        """));

        String summary = ExceptionSummaryUtil.summarizeForClient(exception);

        assertTrue(summary.contains("第53行附近出现错误"));
        assertTrue(summary.contains("无法解析的成员访问表达式[a.htids]"));
        assertFalse(summary.contains("StatementCallback"));
        assertFalse(summary.contains("SQL [SELECT"));
        assertFalse(summary.contains("MRP_CalcMaterialsumListTab"));
        assertFalse(summary.contains("JdbcTemplate"));
        assertFalse(summary.contains("org.springframework"));
        assertFalse(summary.contains("common frames omitted"));
        assertTrue(summary.length() <= 300);
    }

    @Test
    void baseHandlerDoesNotPutStackTraceArrayIntoClientResponse() throws Exception {
        String source = Files.readString(Path.of("src/main/java/org/example/Api/BaseHandler.java"));

        assertFalse(source.contains("Arrays.toString(ex.getCause().getStackTrace())"));
        assertFalse(source.contains("response.setMsg(errMsg.substring(errMsg.indexOf(\"execute sql error\")))"));
    }
}
