#[cfg(test)]
mod tests {
    use crate::parser::query_builder::{
        Condition, QueryBuilder, build_insert_placeholders_for_entries_with_types,
        build_where_clause,
    };
    use serde_json::json;
    use std::collections::HashMap;

    /// ## `build_where_clause_casts_uuid_comparisons_to_text_by_default`
    /// Tests that the build_where_clause function casts UUID comparisons to text by default.
    ///
    /// # Arguments
    ///
    /// * `conditions` - The conditions to build the where clause for.
    ///
    /// # Returns
    ///
    #[test]
    fn build_where_clause_casts_uuid_comparisons_to_text_by_default() {
        let conditions: Vec<Condition> = vec![Condition::eq(
            "workspace_id",
            json!("550e8400-e29b-41d4-a716-446655440000"),
        )];

        let (clause, values) = build_where_clause(&conditions, 1).expect("where clause");

        assert_eq!(clause, " WHERE t.\"workspace_id\"::text = $1::text");
        assert_eq!(values, vec![json!("550e8400-e29b-41d4-a716-446655440000")]);
    }

    /// ## `build_where_clause_can_disable_uuid_text_casts`
    /// Tests that the build_where_clause function can disable UUID text casts.
    ///
    /// # Arguments
    ///
    /// * `conditions` - The conditions to build the where clause for.
    ///
    /// # Returns
    ///
    #[test]
    fn build_where_clause_can_disable_uuid_text_casts() {
        let conditions: Vec<Condition> = vec![
            Condition::eq(
                "workspace_id",
                json!("550e8400-e29b-41d4-a716-446655440000"),
            )
            .with_uuid_value_text_cast(false),
        ];

        let (clause, values) = build_where_clause(&conditions, 1).expect("where clause");

        assert_eq!(clause, " WHERE t.\"workspace_id\" = $1");
        assert_eq!(values, vec![json!("550e8400-e29b-41d4-a716-446655440000")]);
    }

    #[test]
    fn query_builder_struct_builds_where_clause() {
        let query_builder = QueryBuilder::new()
            .with_start_index(3)
            .with_condition(Condition::eq("workspace_id", json!("workspace-1")));

        let (clause, values) = query_builder
            .build_where_clause()
            .expect("where clause from QueryBuilder");

        assert_eq!(clause, " WHERE t.\"workspace_id\" = $3");
        assert_eq!(values, vec![json!("workspace-1")]);
    }

    #[test]
    fn build_insert_placeholders_adds_jsonb_cast_with_column_types() {
        let entries = vec![
            ("\"payload\"".to_string(), json!({"source": "test"})),
            (
                "\"created_at\"".to_string(),
                json!("2024-01-15T12:00:00.000Z"),
            ),
        ];
        let column_types = HashMap::from([
            ("payload".to_string(), "jsonb".to_string()),
            (
                "created_at".to_string(),
                "timestamp with time zone".to_string(),
            ),
        ]);

        let (placeholders, bind_values) =
            build_insert_placeholders_for_entries_with_types(&entries, Some(&column_types));

        assert_eq!(placeholders, vec!["$1::jsonb", "$2::timestamptz"]);
        assert_eq!(bind_values.len(), 2);
    }

    #[test]
    fn build_insert_placeholders_preserves_null_without_binding() {
        let entries = vec![
            ("\"payload\"".to_string(), json!(null)),
            ("\"title\"".to_string(), json!("hello")),
        ];
        let column_types = HashMap::from([("payload".to_string(), "jsonb".to_string())]);

        let (placeholders, bind_values) =
            build_insert_placeholders_for_entries_with_types(&entries, Some(&column_types));

        assert_eq!(placeholders, vec!["NULL", "$1"]);
        assert_eq!(bind_values.len(), 1);
        assert_eq!(*bind_values[0], json!("hello"));
    }
}
