//! Dialect and language metadata for Athena query surfaces.
//!
//! The goal is to make backend differences explicit before the driver split
//! happens. Callers can describe whether a request is SQL or CQL, and when it
//! is SQL they can stamp the concrete dialect they expect.

use serde::{Deserialize, Serialize};

/// Broad query language families supported by Athena.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum QueryLanguage {
    Sql,
    Cql,
}

/// SQL dialect flavors Athena can distinguish today.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SqlDialect {
    Generic,
    PostgreSql,
    MySql,
    Sqlite,
    MsSql,
}

/// Canonical query dialect descriptor used by portable query helpers.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "language", rename_all = "snake_case")]
pub enum QueryDialect {
    Sql { dialect: SqlDialect },
    Cql,
}

impl QueryDialect {
    /// Returns the broad language family for this dialect.
    pub fn language(self) -> QueryLanguage {
        match self {
            Self::Sql { .. } => QueryLanguage::Sql,
            Self::Cql => QueryLanguage::Cql,
        }
    }

    /// Returns the SQL dialect when this descriptor represents SQL.
    pub fn sql_dialect(self) -> Option<SqlDialect> {
        match self {
            Self::Sql { dialect } => Some(dialect),
            Self::Cql => None,
        }
    }

    /// Convenience constructor for generic PostgreSQL-flavored SQL.
    pub const fn postgres() -> Self {
        Self::Sql {
            dialect: SqlDialect::PostgreSql,
        }
    }

    /// Convenience constructor for generic CQL.
    pub const fn cql() -> Self {
        Self::Cql
    }
}

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

    #[test]
    fn postgres_reports_sql_language() {
        let dialect = QueryDialect::postgres();
        assert_eq!(dialect.language(), QueryLanguage::Sql);
        assert_eq!(dialect.sql_dialect(), Some(SqlDialect::PostgreSql));
    }

    #[test]
    fn cql_has_no_sql_dialect() {
        let dialect = QueryDialect::cql();
        assert_eq!(dialect.language(), QueryLanguage::Cql);
        assert_eq!(dialect.sql_dialect(), None);
    }
}
