//! ## `operator` for the query builder.
//!
//! This module contains the operators for the query builder.
//!
//! ### `ConditionOperator`
//! The `ConditionOperator` enum is used to represent the operators for the query builder.
//!
//! #### `Eq`
//! The `Eq` operator is used to represent the equality operator.
//!
//! #### `Neq`
//! The `Neq` operator is used to represent the not equal operator.
//!
//! #### `Gt`
//! The `Gt` operator is used to represent the greater than operator.
//!
//! #### `Gte`
//! The `Gte` operator is used to represent the greater than or equal to operator.
//!
//! #### `Lt`
//! The `Lt` operator is used to represent the less than operator.
//!
//! #### `Lte`
//! The `Lte` operator is used to represent the less than or equal to operator.
//!
//! #### `Like`
//! The `Like` operator is used to represent the like operator.
//!
//! #### `ILike`
//! The `ILike` operator is used to represent the case-insensitive like operator.
//!
//! #### `Is`
//! The `Is` operator is used to represent the is operator.
//!
//! #### `In`
//! The `In` operator is used to represent the in operator.
//!
//! #### `Contains`
//! The `Contains` operator is used to represent the contains operator.
//!

use serde_json::Value;

use crate::query_builder::{
    Condition, ConditionOperator, build_array_clause, build_in_clause, build_is_clause,
    create_placeholder_clause,
};

/// ## `format_condition_clause`
/// # Condition Operator Descriptions
///
/// * `ConditionOperator::Eq` - Formats an equality condition.
/// * `ConditionOperator::Neq` - Formats a not equal condition.
/// * `ConditionOperator::Gt` - Formats a greater than condition.
/// * `ConditionOperator::Gte` - Formates a greater than or equal to condition.
/// * `ConditionOperator::Lt` - Formats a less than condition.
/// * `ConditionOperator::Lte` - Formats a less than or equal to condition.
/// * `ConditionOperator::Like` - Formats a like condition.
/// * `ConditionOperator::ILike` - Formats a case-insensitive like condition.
/// * `ConditionOperator::Is` - Formats an is condition.
/// * `ConditionOperator::In` - Formats an in condition.
/// * `ConditionOperator::Contains` - Formats a contains condition.
/// * `ConditionOperator::Contained` - Formats a contained condition.
///
pub fn format_condition_clause(
    column: &str,
    condition: &Condition,
    idx: &mut usize,
    values: &mut Vec<Value>,
) -> Option<String> {
    let clause: String = match condition.operator {
        ConditionOperator::Eq => create_placeholder_clause(
            column,
            idx,
            values,
            condition,
            condition.values.first()?,
            "=",
        )?,
        ConditionOperator::Neq => create_placeholder_clause(
            column,
            idx,
            values,
            condition,
            condition.values.first()?,
            "<>",
        )?,
        ConditionOperator::Gt => create_placeholder_clause(
            column,
            idx,
            values,
            condition,
            condition.values.first()?,
            ">",
        )?,
        ConditionOperator::Gte => create_placeholder_clause(
            column,
            idx,
            values,
            condition,
            condition.values.first()?,
            ">=",
        )?,
        ConditionOperator::Lt => create_placeholder_clause(
            column,
            idx,
            values,
            condition,
            condition.values.first()?,
            "<",
        )?,
        ConditionOperator::Lte => create_placeholder_clause(
            column,
            idx,
            values,
            condition,
            condition.values.first()?,
            "<=",
        )?,
        ConditionOperator::Like => create_placeholder_clause(
            column,
            idx,
            values,
            condition,
            condition.values.first()?,
            "LIKE",
        )?,
        ConditionOperator::ILike => create_placeholder_clause(
            column,
            idx,
            values,
            condition,
            condition.values.first()?,
            "ILIKE",
        )?,
        ConditionOperator::Is => build_is_clause(column, condition, idx, values)?,
        ConditionOperator::In => build_in_clause(column, condition, idx, values)?,
        ConditionOperator::Contains => build_array_clause(column, condition, idx, values, "@>")?,
        ConditionOperator::Contained => build_array_clause(column, condition, idx, values, "<@")?,
    };

    let clause = if condition.negated {
        format!("NOT ({})", clause)
    } else {
        clause
    };

    Some(clause)
}
