use crate::parser::query_builder::Condition;
use crate::utils::format::camel_to_snake_case;
use serde_json::Value;

/// Internal representation of a simple equality filter provided by gateway requests.
///
#[derive(Debug)]
pub struct RequestCondition {
    pub eq_column: String,
    pub eq_value: Value,
}

/// Checks if a string is in camelCase format.
///
/// Returns `true` if the string contains at least one uppercase letter
/// that is not at the start of the string, indicating camelCase format.
fn is_camel_case(s: &str) -> bool {
    s.chars()
        .skip(1) // Skip the first character
        .any(|c| c.is_ascii_uppercase())
}

impl RequestCondition {
    /// `RequestCondition` new implementation
    ///
    /// ## Arguments
    /// - `eq_column`: String
    /// - `eq_value`: Value
    ///
    pub fn new(eq_column: String, eq_value: Value) -> Self {
        Self {
            eq_column,
            eq_value,
        }
    }
}

/// Converts normalized request conditions into Postgres query conditions.
///
/// If the column name is already in camelCase format, it bypasses the converter
/// and queries the database with the actual camelCase column name.
pub fn to_query_conditions(
    conditions: &[RequestCondition],
    convert_camel_case: bool,
    auto_cast_uuid_filter_values_to_text: bool,
) -> Vec<Condition> {
    conditions
        .iter()
        .map(|condition: &RequestCondition| {
            // Check if the column is already in camelCase - if so, bypass conversion
            let is_already_camel_case: bool = is_camel_case(&condition.eq_column);
            let column_name: String = if convert_camel_case && !is_already_camel_case {
                let converted: String = camel_to_snake_case(&condition.eq_column);
                converted
            } else {
                condition.eq_column.clone()
            };
            let query_condition: Condition =
                Condition::eq(&column_name, condition.eq_value.clone())
                    .with_uuid_value_text_cast(auto_cast_uuid_filter_values_to_text);
            query_condition
        })
        .collect()
}
