use proc_macro::TokenStream;

mod column_attr;
mod model_derive;
mod sql_macro;

/// Derive macro for implementing the `Model` trait on a struct.
///
/// Generates:
/// - `impl Model for T { ... }` with table name, column metadata, primary keys
/// - `TColumns` struct with typed `Column<T>` fields
/// - `impl T { fn columns() -> TColumns { ... } }`
/// - `impl FromRow for T { ... }`
///
/// # Example
/// ```ignore
/// #[derive(Model, Debug, Clone)]
/// #[model(table = "users")]
/// pub struct User {
///     #[column(primary_key, auto_increment)]
///     pub id: Option<i64>,
///
///     #[column]
///     pub name: String,
/// }
/// ```
#[proc_macro_derive(Model, attributes(model, column, has_many, belongs_to, has_one))]
pub fn derive_model(input: TokenStream) -> TokenStream {
    model_derive::derive_model_impl(input)
}

/// SQL expression macro with compile-time validation via sqlparser-rs.
///
/// Supports:
/// - Column references: `c.field_name` → extracted as column name
/// - Bind parameters: `{expr}` → `?` placeholder with Rust expression as param
/// - SQL operators: `>`, `<`, `LIKE`, `BETWEEN`, `IN`, `IS NULL`, etc.
///
/// Returns a `Condition::Raw` that can be used in `find()` condition arrays.
///
/// # Examples
/// ```ignore
/// sql!(c.age > {18})
/// sql!(c.name LIKE {"%test%"})
/// sql!(c.score BETWEEN {60} AND {100})
/// sql!(c.deleted_at IS NULL)
/// ```
#[proc_macro]
pub fn sql(input: TokenStream) -> TokenStream {
    sql_macro::sql_macro_impl(input)
}
