use super::ClickhouseClient;

// ---------------------------------------------------------------------------
// Helper: execute SQL against the `sql_val_test` database
// ---------------------------------------------------------------------------

fn execute_sql(sql: &str) -> Result<String, String> {
    let url =
        "http://localhost:8123/?user=default&password=clickhouse&database=sql_val_test".to_string();
    let client = reqwest::blocking::Client::new();
    let response = client
        .post(&url)
        .body(sql.to_string())
        .send()
        .map_err(|e| format!("Request failed: {}", e))?;

    if response.status().is_success() {
        response
            .text()
            .map_err(|e| format!("Failed to read response: {}", e))
    } else {
        let status = response.status();
        let body = response.text().unwrap_or_default();
        Err(format!("HTTP {}: {}", status, body))
    }
}

// ---------------------------------------------------------------------------
// Infrastructure setup
// ---------------------------------------------------------------------------

fn setup_infra(client: &ClickhouseClient) -> Result<(), String> {
    // Create database
    client.execute("CREATE DATABASE IF NOT EXISTS sql_val_test")?;

    // typed_test — general purpose table with rich column types
    client.execute("DROP TABLE IF EXISTS sql_val_test.typed_test")?;
    client.execute(
        "CREATE TABLE sql_val_test.typed_test (\
         id Int32, \
         dt DateTime, \
         d Date, \
         s String, \
         i Int64, \
         f Float64, \
         arr Array(String), \
         arr_int Array(UInt8), \
         ipv4 IPv4, \
         ipv6 IPv6, \
         uuid UUID, \
         js String\
         ) ENGINE = MergeTree() ORDER BY id",
    )?;
    client.execute(
        "INSERT INTO sql_val_test.typed_test VALUES \
         (1, '2024-01-15 10:30:00', '2024-01-15', 'hello world', 42, 3.14, \
         ['a','b','c'], [1,0,1], '127.0.0.1', '::1', \
         '01234567-89ab-cdef-0123-456789abcdef', '{\"key\": \"value\", \"num\": 42}')",
    )?;

    // character table (test_cfg schema)
    client.execute("DROP TABLE IF EXISTS sql_val_test.`character`")?;
    client.execute(
        "CREATE TABLE sql_val_test.`character` (\
         id Int32, character String, font_size Int32, size_w Int32, size_h Int32, \
         font_id Int32, ascii Int32, created_at DateTime, user_data String\
         ) ENGINE = MergeTree() ORDER BY id",
    )?;
    client.execute(
        "INSERT INTO sql_val_test.`character` VALUES \
         (1, 'A', 12, 100, 200, 1, 65, '2024-01-15 10:30:00', '{\"key\": \"value\"}'), \
         (2, 'B', 14, 150, 250, 1, 66, '2024-06-20 14:00:00', '{\"key\": \"value2\"}'), \
         (3, 'C', 16, 80, 120, 2, 67, '2023-07-04 08:00:00', '{\"key\": \"value3\"}')",
    )?;

    // glyph table (test_cfg schema)
    client.execute("DROP TABLE IF EXISTS sql_val_test.`glyph`")?;
    client.execute(
        "CREATE TABLE sql_val_test.`glyph` (\
         id Int32, image String, aspect Float64, tokens String\
         ) ENGINE = MergeTree() ORDER BY id",
    )?;
    client.execute(
        "INSERT INTO sql_val_test.`glyph` VALUES \
         (1, 'img1', 1.23, 'tok1'), (2, 'img2', 4.56, 'tok2')",
    )?;

    // font table (test_cfg schema)
    client.execute("DROP TABLE IF EXISTS sql_val_test.`font`")?;
    client.execute(
        "CREATE TABLE sql_val_test.`font` (\
         id Int32, name String, variant String, language String\
         ) ENGINE = MergeTree() ORDER BY id",
    )?;
    client.execute(
        "INSERT INTO sql_val_test.`font` VALUES \
         (1, 'Arial', 'Regular', 'en'), (2, 'Helvetica', 'Bold', 'en')",
    )?;

    // rmt_test — ReplacingMergeTree for FINAL testing
    client.execute("DROP TABLE IF EXISTS sql_val_test.`rmt_test`")?;
    client.execute(
        "CREATE TABLE sql_val_test.`rmt_test` (\
         id Int32, s String, ver Int32\
         ) ENGINE = ReplacingMergeTree(ver) ORDER BY id",
    )?;
    client.execute("INSERT INTO sql_val_test.`rmt_test` VALUES (1, 'a', 1), (1, 'b', 2)")?;

    // sample_test — MergeTree with SAMPLE BY
    client.execute("DROP TABLE IF EXISTS sql_val_test.`sample_test`")?;
    client.execute(
        "CREATE TABLE sql_val_test.`sample_test` (\
         id Int32, hash UInt32\
         ) ENGINE = MergeTree() ORDER BY (intHash32(hash), id) SAMPLE BY intHash32(hash)",
    )?;
    client.execute(
        "INSERT INTO sql_val_test.`sample_test` SELECT number, number FROM numbers(1000)",
    )?;

    Ok(())
}

// ---------------------------------------------------------------------------
// The big test
// ---------------------------------------------------------------------------

#[test]
fn validate_all_queries() {
    let client = ClickhouseClient::new();
    if !client.is_available() {
        eprintln!("ClickHouse is not available — skipping sql_validation test");
        return;
    }

    // Set up tables and data
    if let Err(e) = setup_infra(&client) {
        panic!("Infrastructure setup failed: {}", e);
    }

    // Allow a moment for ClickHouse to finish processing mutations
    std::thread::sleep(std::time::Duration::from_millis(200));

    // ── All queries to validate ─────────────────────────────────────────
    let queries: Vec<(&str, &str)> = vec![
        // === Standalone (no table) ===
        ("now()", "SELECT now()"),
        ("now64()", "SELECT now64(3)"),
        ("today()", "SELECT today()"),
        ("yesterday()", "SELECT yesterday()"),
        ("generateUUIDv4()", "SELECT generateUUIDv4()"),
        (
            "domain_literal",
            "SELECT domain('https://example.com/path')",
        ),
        (
            "toDateTime_literal",
            "SELECT toDateTime('2024-01-15 10:30:00')",
        ),
        ("rowNumberInAllBlocks()", "SELECT rowNumberInAllBlocks()"),
        ("version()", "SELECT version()"),
        ("uptime()", "SELECT uptime()"),
        ("rand()", "SELECT rand()"),
        ("toYYYYMM_now", "SELECT toYYYYMM(now())"),
        // === DateTime functions (typed_test.dt) ===
        ("toDateTime_col", "SELECT toDateTime(`dt`) FROM typed_test"),
        (
            "toDateTime64_col",
            "SELECT toDateTime64(`dt`, 3) FROM typed_test",
        ),
        ("toDate_col", "SELECT toDate(`dt`) FROM typed_test"),
        ("toDate32_col", "SELECT toDate32(`dt`) FROM typed_test"),
        ("toYear_col", "SELECT toYear(`dt`) FROM typed_test"),
        ("toMonth_col", "SELECT toMonth(`dt`) FROM typed_test"),
        (
            "toDayOfMonth_col",
            "SELECT toDayOfMonth(`dt`) FROM typed_test",
        ),
        ("toHour_col", "SELECT toHour(`dt`) FROM typed_test"),
        ("toMinute_col", "SELECT toMinute(`dt`) FROM typed_test"),
        ("toSecond_col", "SELECT toSecond(`dt`) FROM typed_test"),
        ("toStartOfDay", "SELECT toStartOfDay(`dt`) FROM typed_test"),
        (
            "toStartOfMonth",
            "SELECT toStartOfMonth(`dt`) FROM typed_test",
        ),
        (
            "toStartOfYear",
            "SELECT toStartOfYear(`dt`) FROM typed_test",
        ),
        (
            "toStartOfWeek",
            "SELECT toStartOfWeek(`dt`) FROM typed_test",
        ),
        (
            "toStartOfHour",
            "SELECT toStartOfHour(`dt`) FROM typed_test",
        ),
        (
            "toStartOfMinute",
            "SELECT toStartOfMinute(`dt`) FROM typed_test",
        ),
        (
            "toStartOfInterval",
            "SELECT toStartOfInterval(`dt`, INTERVAL 1 HOUR) FROM typed_test",
        ),
        (
            "dateDiff",
            "SELECT dateDiff('day', `dt`, `dt`) FROM typed_test",
        ),
        ("dateAdd", "SELECT dateAdd(DAY, 5, `dt`) FROM typed_test"),
        ("dateSub", "SELECT dateSub(DAY, 5, `dt`) FROM typed_test"),
        (
            "formatDateTime",
            "SELECT formatDateTime(`dt`, '%Y-%m-%d') FROM typed_test",
        ),
        (
            "parseDateTime",
            "SELECT parseDateTime('2024-01-15', '%Y-%m-%d')",
        ),
        (
            "toUnixTimestamp",
            "SELECT toUnixTimestamp(`dt`) FROM typed_test",
        ),
        ("fromUnixTimestamp", "SELECT fromUnixTimestamp(1700000000)"),
        ("toYYYYMM_col", "SELECT toYYYYMM(`dt`) FROM typed_test"),
        ("toYYYYMMDD_col", "SELECT toYYYYMMDD(`dt`) FROM typed_test"),
        // === Array functions (typed_test.arr, arr_int) ===
        ("arrayJoin", "SELECT arrayJoin(`arr`) FROM typed_test"),
        ("groupArray", "SELECT groupArray(`s`) FROM typed_test"),
        (
            "groupUniqArray",
            "SELECT groupUniqArray(`s`) FROM typed_test",
        ),
        ("arraySort", "SELECT arraySort(`arr`) FROM typed_test"),
        (
            "arrayReverseSort",
            "SELECT arrayReverseSort(`arr`) FROM typed_test",
        ),
        ("arrayReverse", "SELECT arrayReverse(`arr`) FROM typed_test"),
        ("arrayFlatten", "SELECT arrayFlatten([['a','b'],['c']])"),
        ("arrayCompact", "SELECT arrayCompact(`arr`) FROM typed_test"),
        (
            "arrayDistinct",
            "SELECT arrayDistinct(`arr`) FROM typed_test",
        ),
        (
            "arrayConcat",
            "SELECT arrayConcat(`arr`, `arr`) FROM typed_test",
        ),
        (
            "arraySlice",
            "SELECT arraySlice(`arr`, 1, 2) FROM typed_test",
        ),
        ("has", "SELECT has(`arr`, 'a') FROM typed_test"),
        ("hasAll", "SELECT hasAll(`arr`, ['a','b']) FROM typed_test"),
        ("hasAny", "SELECT hasAny(`arr`, ['a','z']) FROM typed_test"),
        ("indexOf", "SELECT indexOf(`arr`, 'b') FROM typed_test"),
        ("arrayCount", "SELECT arrayCount(`arr_int`) FROM typed_test"),
        ("arraySum", "SELECT arraySum([1, 2, 3])"),
        ("arrayAvg", "SELECT arrayAvg([1.0, 2.0, 3.0])"),
        ("arrayMin", "SELECT arrayMin([1, 2, 3])"),
        ("arrayMax", "SELECT arrayMax([1, 2, 3])"),
        ("length", "SELECT length(`s`) FROM typed_test"),
        // === String functions (typed_test.s) ===
        ("toString", "SELECT toString(`i`) FROM typed_test"),
        (
            "splitByChar",
            "SELECT splitByChar(' ', `s`) FROM typed_test",
        ),
        (
            "splitByString",
            "SELECT splitByString('l', `s`) FROM typed_test",
        ),
        (
            "replaceAll",
            "SELECT replaceAll(`s`, 'l', 'L') FROM typed_test",
        ),
        (
            "replaceOne",
            "SELECT replaceOne(`s`, 'l', 'L') FROM typed_test",
        ),
        ("concat", "SELECT concat(`s`, ' world') FROM typed_test"),
        (
            "concatWithSeparator",
            "SELECT concatWithSeparator('-', 'a', 'b', 'c')",
        ),
        ("substring", "SELECT substring(`s`, 1, 5) FROM typed_test"),
        ("trimBoth", "SELECT trimBoth('  hello  ')"),
        ("trimLeft", "SELECT trimLeft('  hello  ')"),
        ("trimRight", "SELECT trimRight('  hello  ')"),
        ("base64Encode", "SELECT base64Encode('hello')"),
        ("base64Decode", "SELECT base64Decode(base64Encode('hello'))"),
        ("lengthUTF8", "SELECT lengthUTF8(`s`) FROM typed_test"),
        ("reverse", "SELECT reverse(`s`) FROM typed_test"),
        (
            "extractAll",
            "SELECT extractAll(`s`, '\\\\d+') FROM typed_test",
        ),
        ("match_func", "SELECT match(`s`, 'hello') FROM typed_test"),
        ("like_func", "SELECT like(`s`, '%hello%') FROM typed_test"),
        ("notLike", "SELECT notLike(`s`, '%xyz%') FROM typed_test"),
        (
            "multiSearchAny",
            "SELECT multiSearchAny(`s`, ['hel', 'wor']) FROM typed_test",
        ),
        ("position", "SELECT position(`s`, 'world') FROM typed_test"),
        // === Type conversion (typed_test) ===
        ("toUInt8", "SELECT toUInt8(`i`) FROM typed_test"),
        ("toUInt16", "SELECT toUInt16(`i`) FROM typed_test"),
        ("toUInt32", "SELECT toUInt32(`i`) FROM typed_test"),
        ("toUInt64", "SELECT toUInt64(`i`) FROM typed_test"),
        ("toInt8", "SELECT toInt8(`i`) FROM typed_test"),
        ("toInt16", "SELECT toInt16(`i`) FROM typed_test"),
        ("toInt32", "SELECT toInt32(`i`) FROM typed_test"),
        ("toInt64", "SELECT toInt64(`i`) FROM typed_test"),
        ("toFloat32", "SELECT toFloat32(`i`) FROM typed_test"),
        ("toFloat64", "SELECT toFloat64(`i`) FROM typed_test"),
        ("toDecimal32", "SELECT toDecimal32(`i`, 2) FROM typed_test"),
        ("toDecimal64", "SELECT toDecimal64(`i`, 4) FROM typed_test"),
        (
            "toDecimal128",
            "SELECT toDecimal128(`i`, 8) FROM typed_test",
        ),
        (
            "toFixedString",
            "SELECT toFixedString(`s`, 20) FROM typed_test",
        ),
        ("toUUID", "SELECT toUUID(`uuid`) FROM typed_test"),
        ("toIPv4", "SELECT toIPv4(`ipv4`) FROM typed_test"),
        ("toIPv6", "SELECT toIPv6(`ipv6`) FROM typed_test"),
        ("toTypeName", "SELECT toTypeName(`s`) FROM typed_test"),
        (
            "reinterpretAsString",
            "SELECT reinterpretAsString(`i`) FROM typed_test",
        ),
        (
            "reinterpretAsUInt64",
            "SELECT reinterpretAsUInt64(`s`) FROM typed_test",
        ),
        ("CAST_comma", "SELECT CAST(`i`, 'String') FROM typed_test"),
        ("CAST_AS", "SELECT CAST(`i` AS String) FROM typed_test"),
        // === Hash functions ===
        ("sipHash64", "SELECT sipHash64(`s`) FROM typed_test"),
        ("sipHash128", "SELECT sipHash128(`s`) FROM typed_test"),
        ("cityHash64", "SELECT cityHash64(`s`) FROM typed_test"),
        ("xxHash64", "SELECT xxHash64(`s`) FROM typed_test"),
        (
            "murmurHash3_64",
            "SELECT murmurHash3_64(`s`) FROM typed_test",
        ),
        ("MD5_ch", "SELECT MD5(`s`) FROM typed_test"),
        ("SHA256", "SELECT SHA256(`s`) FROM typed_test"),
        ("halfMD5", "SELECT halfMD5(`s`) FROM typed_test"),
        // === Aggregate functions ===
        ("uniq", "SELECT uniq(`s`) FROM typed_test"),
        ("uniqExact", "SELECT uniqExact(`s`) FROM typed_test"),
        ("uniqCombined", "SELECT uniqCombined(`s`) FROM typed_test"),
        ("uniqHLL12", "SELECT uniqHLL12(`s`) FROM typed_test"),
        ("argMin", "SELECT argMin(`s`, `i`) FROM typed_test"),
        ("argMax", "SELECT argMax(`s`, `i`) FROM typed_test"),
        ("quantile", "SELECT quantile(`i`) FROM typed_test"),
        ("quantileExact", "SELECT quantileExact(`i`) FROM typed_test"),
        (
            "quantiles_parametric",
            "SELECT quantiles(0.5, 0.9)(`i`) FROM typed_test",
        ),
        ("topK_parametric", "SELECT topK(10)(`s`) FROM typed_test"),
        ("sumIf", "SELECT sumIf(`i`, `i` > 10) FROM typed_test"),
        ("countIf", "SELECT countIf(`i` > 5) FROM typed_test"),
        ("avgIf", "SELECT avgIf(`f`, `i` > 10) FROM typed_test"),
        ("minIf", "SELECT minIf(`i`, `i` > 10) FROM typed_test"),
        ("maxIf", "SELECT maxIf(`i`, `i` > 10) FROM typed_test"),
        ("any_func", "SELECT any(`s`) FROM typed_test"),
        ("anyLast", "SELECT anyLast(`s`) FROM typed_test"),
        ("groupBitAnd", "SELECT groupBitAnd(`i`) FROM typed_test"),
        ("groupBitOr", "SELECT groupBitOr(`i`) FROM typed_test"),
        ("groupBitXor", "SELECT groupBitXor(`i`) FROM typed_test"),
        ("median", "SELECT median(`i`) FROM typed_test"),
        // === Conditional ===
        (
            "if_func",
            "SELECT if(`i` > 10, 'big', 'small') FROM typed_test",
        ),
        (
            "multiIf",
            "SELECT multiIf(`i` > 10, 'big', `i` > 5, 'medium', 'small') FROM typed_test",
        ),
        // === URL ===
        ("domain_col", "SELECT domain('https://example.com/path')"),
        (
            "topLevelDomain",
            "SELECT topLevelDomain('https://example.com/path')",
        ),
        (
            "path_func",
            "SELECT path('https://example.com/path/to/page')",
        ),
        ("protocol_func", "SELECT protocol('https://example.com')"),
        (
            "extractURLParameter",
            "SELECT extractURLParameter('https://example.com?id=123', 'id')",
        ),
        // === JSON ===
        (
            "JSONExtract",
            "SELECT JSONExtract(`js`, 'key', 'String') FROM typed_test",
        ),
        (
            "JSONExtractString",
            "SELECT JSONExtractString(`js`, 'key') FROM typed_test",
        ),
        (
            "JSONExtractUInt",
            "SELECT JSONExtractUInt(`js`, 'num') FROM typed_test",
        ),
        (
            "JSONExtractInt",
            "SELECT JSONExtractInt(`js`, 'num') FROM typed_test",
        ),
        (
            "JSONExtractFloat",
            "SELECT JSONExtractFloat(`js`, 'num') FROM typed_test",
        ),
        (
            "JSONExtractBool",
            "SELECT JSONExtractBool(`js`, 'key') FROM typed_test",
        ),
        (
            "JSONExtractArrayRaw",
            "SELECT JSONExtractArrayRaw(`js`, 'key') FROM typed_test",
        ),
        ("JSONHas", "SELECT JSONHas(`js`, 'key') FROM typed_test"),
        (
            "JSONLength",
            "SELECT JSONLength(`js`, 'key') FROM typed_test",
        ),
        ("JSONType", "SELECT JSONType(`js`, 'key') FROM typed_test"),
        // === Math ===
        ("exp", "SELECT exp(`i`) FROM typed_test"),
        ("log", "SELECT log(`f`) FROM typed_test"),
        ("log2", "SELECT log2(`f`) FROM typed_test"),
        ("log10", "SELECT log10(`f`) FROM typed_test"),
        ("sqrt", "SELECT sqrt(`i`) FROM typed_test"),
        ("cbrt", "SELECT cbrt(`i`) FROM typed_test"),
        ("power", "SELECT power(`i`, 2) FROM typed_test"),
        ("intDiv", "SELECT intDiv(`i`, 2) FROM typed_test"),
        (
            "intDivOrZero",
            "SELECT intDivOrZero(`i`, 2) FROM typed_test",
        ),
        (
            "moduloOrZero",
            "SELECT moduloOrZero(`i`, 2) FROM typed_test",
        ),
        // === Null ===
        ("isNull", "SELECT isNull(NULL)"),
        ("isNotNull", "SELECT isNotNull('x')"),
        ("ifNull", "SELECT ifNull(NULL, 'default')"),
        ("nullIf", "SELECT nullIf('hello', '')"),
        ("assumeNotNull", "SELECT assumeNotNull('x')"),
        ("toNullable", "SELECT toNullable(`i`) FROM typed_test"),
        // === Other (with deprecation settings) ===
        (
            "runningDifference",
            "SELECT runningDifference(number) FROM numbers(5) SETTINGS allow_deprecated_error_prone_window_functions = 1",
        ),
        (
            "neighbor",
            "SELECT neighbor(number, 2) FROM numbers(5) SETTINGS allow_deprecated_error_prone_window_functions = 1",
        ),
        // === Nested ===
        (
            "nested_toStartOfMonth_toDate",
            "SELECT toStartOfMonth(toDate(`dt`)) FROM typed_test",
        ),
        ("toString_i", "SELECT toString(`i`) FROM typed_test"),
        // === sea-query built-in Func ===
        ("MAX", "SELECT MAX(`i`) FROM typed_test"),
        ("MIN", "SELECT MIN(`i`) FROM typed_test"),
        ("SUM", "SELECT SUM(`i`) FROM typed_test"),
        ("AVG", "SELECT AVG(`f`) FROM typed_test"),
        ("ABS", "SELECT ABS(`i`) FROM typed_test"),
        ("COUNT", "SELECT COUNT(`s`) FROM typed_test"),
        (
            "COUNT_DISTINCT",
            "SELECT COUNT(DISTINCT `s`) FROM typed_test",
        ),
        ("CHAR_LENGTH", "SELECT CHAR_LENGTH(`s`) FROM typed_test"),
        (
            "GREATEST",
            "SELECT greatest(`i`, toInt64(`f`)) FROM typed_test",
        ),
        ("LEAST", "SELECT least(`i`, toInt64(`f`)) FROM typed_test"),
        ("IFNULL", "SELECT IFNULL(`s`, 'default') FROM typed_test"),
        ("CAST_AS_sea", "SELECT CAST(`i` AS String) FROM typed_test"),
        (
            "COALESCE",
            "SELECT COALESCE(`s`, 'default') FROM typed_test",
        ),
        ("LOWER", "SELECT LOWER(`s`) FROM typed_test"),
        ("UPPER", "SELECT UPPER(`s`) FROM typed_test"),
        ("BIT_AND", "SELECT BIT_AND(`i`) FROM typed_test"),
        ("BIT_OR", "SELECT BIT_OR(`i`) FROM typed_test"),
        ("ROUND", "SELECT ROUND(`f`) FROM typed_test"),
        ("ROUND_prec", "SELECT ROUND(`f`, 2) FROM typed_test"),
        ("MD5_sea", "SELECT MD5(`s`) FROM typed_test"),
        // === DML on character/glyph/font tables ===
        (
            "select_cols",
            "SELECT `character`, `size_w`, `size_h` FROM `character` LIMIT 10",
        ),
        (
            "select_where",
            "SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `size_w` = 100",
        ),
        (
            "select_where_and",
            "SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `size_w` = 100 AND `size_h` = 200",
        ),
        (
            "select_join",
            "SELECT `character`, `font`.`name` FROM `character` LEFT JOIN `font` ON `character`.`font_id` = `font`.`id`",
        ),
        (
            "select_group_by",
            "SELECT `character` FROM `character` GROUP BY `character`",
        ),
        (
            "select_order_by",
            "SELECT `character` FROM `character` ORDER BY `character` ASC",
        ),
        (
            "select_distinct",
            "SELECT DISTINCT `character` FROM `character`",
        ),
        ("select_alias", "SELECT `character` AS `C` FROM `character`"),
        (
            "select_prewhere",
            "SELECT `character` FROM `character` PREWHERE `font_id` = 1",
        ),
        (
            "select_settings",
            "SELECT `character` FROM `character` SETTINGS max_threads = 2, max_block_size = 65505",
        ),
        (
            "select_where_func",
            "SELECT `character` FROM `character` WHERE toYear(`created_at`) = 2024",
        ),
        // FINAL with ReplacingMergeTree
        ("select_final", "SELECT `s` FROM `rmt_test` FINAL"),
        // SAMPLE with proper table
        (
            "select_sample",
            "SELECT `id` FROM `sample_test` SAMPLE 0.1 LIMIT 5",
        ),
        // Glyph DML — these mutate data so we run them last
        (
            "glyph_insert",
            "INSERT INTO `glyph` (`aspect`, `image`) VALUES (5.15, '12A'), (4.21, '123')",
        ),
        (
            "glyph_select_order",
            "SELECT `aspect` FROM `glyph` ORDER BY `aspect` ASC",
        ),
        (
            "glyph_group_having",
            "SELECT `aspect`, MAX(`image`) FROM `glyph` GROUP BY `aspect` HAVING `aspect` > 2",
        ),
        (
            "glyph_subquery",
            "SELECT `aspect` FROM (SELECT `image`, `aspect` FROM `glyph`) AS `subglyph`",
        ),
        (
            "glyph_update",
            "ALTER TABLE `glyph` UPDATE `aspect` = 1.23, `image` = 'abc' WHERE `id` = 1",
        ),
        ("glyph_delete", "ALTER TABLE `glyph` DELETE WHERE `id` = 1"),
    ];

    // ── Run every query and collect failures ────────────────────────────
    let mut failures: Vec<(String, String, String)> = Vec::new(); // (name, sql, error)

    for (name, sql) in &queries {
        match execute_sql(sql) {
            Ok(_) => {}
            Err(e) => {
                failures.push((name.to_string(), sql.to_string(), e));
            }
        }
    }

    // ── Report ──────────────────────────────────────────────────────────
    if failures.is_empty() {
        eprintln!(
            "✓ All {} queries validated successfully against ClickHouse",
            queries.len()
        );
    } else {
        let mut report = format!(
            "\n\n❌ {}/{} queries FAILED against ClickHouse:\n\n",
            failures.len(),
            queries.len()
        );
        for (i, (name, sql, error)) in failures.iter().enumerate() {
            report.push_str(&format!(
                "--- FAILURE #{}: {} ---\n\
                 SQL:   {}\n\
                 ERROR: {}\n\n",
                i + 1,
                name,
                sql,
                error.trim()
            ));
        }
        panic!("{}", report);
    }
}
