//! SQL transpilation between dialects using polyglot-sql.
//!
//! Note: polyglot-sql's transpile function uses deep recursion that can overflow
//! the default 8MB thread stack. Transpilation runs on a thread with a larger stack.

use super::dialect_map::to_polyglot_dialect;
use super::types::TranspileResult;
use crate::schema::types::SqlDialect;

/// Stack size for transpilation threads (32MB).
const TRANSPILE_THREAD_STACK_SIZE: usize = 32 * 1024 * 1024;

/// Transpile a SQL query from one dialect to another.
///
/// Returns a [`TranspileResult`] with the transpiled SQL statements or an error.
pub fn transpile(sql: &str, source: SqlDialect, target: SqlDialect) -> TranspileResult {
    let sql_owned = sql.to_string();
    std::thread::Builder::new()
        .stack_size(TRANSPILE_THREAD_STACK_SIZE)
        .spawn(move || transpile_inner(&sql_owned, source, target))
        .unwrap_or_else(|e| {
            panic!("failed to spawn transpilation thread: {e}");
        })
        .join()
        .unwrap_or_else(|_| TranspileResult {
            original_sql: String::new(),
            source_dialect: source.to_string(),
            target_dialect: target.to_string(),
            transpiled_sql: vec![],
            success: false,
            error: Some("transpilation thread panicked".to_string()),
        })
}

/// Inner implementation of transpile.
fn transpile_inner(sql: &str, source: SqlDialect, target: SqlDialect) -> TranspileResult {
    let src = to_polyglot_dialect(source);
    let tgt = to_polyglot_dialect(target);

    match polyglot_sql::transpile(sql, src, tgt) {
        Ok(statements) => TranspileResult {
            original_sql: sql.to_string(),
            source_dialect: source.to_string(),
            target_dialect: target.to_string(),
            transpiled_sql: statements,
            success: true,
            error: None,
        },
        Err(e) => TranspileResult {
            original_sql: sql.to_string(),
            source_dialect: source.to_string(),
            target_dialect: target.to_string(),
            transpiled_sql: vec![],
            success: false,
            error: Some(e.to_string()),
        },
    }
}

/// Transpile multiple SQL queries in batch.
///
/// Returns a vector of [`TranspileResult`], one per input query.
pub fn transpile_batch(
    queries: &[&str],
    source: SqlDialect,
    target: SqlDialect,
) -> Vec<TranspileResult> {
    queries
        .iter()
        .map(|sql| transpile(sql, source, target))
        .collect()
}
