use sqlparser::dialect::GenericDialect;
use sqlparser::parser::Parser;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ValidationError {
    #[error("SQL syntax error: {0}")]
    SqlSyntax(String),
    #[error("Unsupported SQL statement: {0}")]
    UnsupportedStatement(String),
    #[error("Empty SQL script")]
    EmptyScript,
}

pub struct SqlValidator;

impl SqlValidator {
    /// Validates a custom transformation SQL script.
    /// It ensures the SQL is syntactically correct and (for now) is a SELECT statement.
    pub fn validate_transformation(sql: &str) -> Result<(), ValidationError> {
        if sql.trim().is_empty() {
            return Err(ValidationError::EmptyScript);
        }

        let dialect = GenericDialect {};
        let ast = Parser::parse_sql(&dialect, sql)
            .map_err(|e: sqlparser::parser::ParserError| ValidationError::SqlSyntax(e.to_string()))?;

        if ast.is_empty() {
            return Err(ValidationError::EmptyScript);
        }

        // For transformation scripts, we only allow SELECT statements for now.
        for statement in ast {
            match statement {
                sqlparser::ast::Statement::Query(_) => continue,
                _ => return Err(ValidationError::UnsupportedStatement(
                    format!("{:?}", statement)
                )),
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid_select() {
        let sql = "SELECT name, email FROM stripe_customers WHERE email IS NOT NULL";
        assert!(SqlValidator::validate_transformation(sql).is_ok());
    }

    #[test]
    fn test_invalid_syntax() {
        let sql = "SELECT name, email FORM stripe_customers"; // FORM instead of FROM
        assert!(SqlValidator::validate_transformation(sql).is_err());
    }

    #[test]
    fn test_unsupported_statement() {
        let sql = "DELETE FROM stripe_customers";
        assert!(SqlValidator::validate_transformation(sql).is_err());
    }
}
