//! The semantic validation engine.
//!
//! Validates SQL queries for logical correctness beyond syntax.
//! Detects patterns like cartesian products, wrong join keys,
//! aggregate/GROUP BY mismatches, NULL comparison issues, and more.

use super::rules::run_all_rules;
use super::types::SemanticResult;
use crate::schema::types::SchemaDefinition;
use crate::validator::engine::validate_with_plan;

/// Check the semantic correctness of a SQL query.
///
/// Parses and plans the query using DataFusion, then walks the logical plan
/// to detect logically incorrect patterns. Returns a [`SemanticResult`] with
/// findings, a semantic score, and the list of passed checks.
///
/// # Example
///
/// ```rust,no_run
/// use altimate_core::semantic::engine::check_semantics;
/// use altimate_core::SchemaDefinition;
///
/// # async fn example() {
/// let schema = SchemaDefinition::from_yaml_file("schema.yaml").unwrap();
/// let result = check_semantics(
///     "SELECT u.name, SUM(o.total_amount) FROM users u JOIN orders o ON u.id = o.user_id",
///     &schema,
/// ).await;
/// println!("Score: {}", result.semantic_score);
/// for finding in &result.findings {
///     println!("  [{}] {}: {}", finding.severity, finding.rule, finding.message);
/// }
/// # }
/// ```
pub async fn check_semantics(sql: &str, schema: &SchemaDefinition) -> SemanticResult {
    // 1. Validate and get the logical plan
    let (validation_result, plan) = validate_with_plan(sql, schema).await;

    if !validation_result.valid || plan.is_none() {
        let errors = validation_result
            .errors
            .iter()
            .map(|e| e.message.clone())
            .collect();
        return SemanticResult::invalid(errors);
    }

    let plan = plan.expect("plan should be Some when valid");

    // 2. Run all semantic rules against the plan
    let (findings, passed_checks) = run_all_rules(&plan, schema);

    // 3. Build the result with computed score
    SemanticResult::with_findings(findings, passed_checks)
}
