use proc_macro::TokenStream;
use quote::quote;
use syn::{DeriveInput, parse_macro_input};

#[proc_macro_derive(FromRow)]
pub fn derive_from_row(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let struct_name = &input.ident;

    let fields = match &input.data {
        syn::Data::Struct(data) => match &data.fields {
            syn::Fields::Named(named) => &named.named,
            _ => panic!("FromRow only supports structs with named fields"),
        },
        _ => panic!("FromRow only supports structs"),
    };

    let field_assignments = fields.iter().enumerate().map(|(i, field)| {
        let name = &field.ident;
        quote! { #name: row.get(#i)? }
    });

    let expanded = quote! {
        impl crate::database::FromRow for #struct_name {
            fn from_row(row: &rusqlite::Row) -> rusqlite::Result<Self> {
                Ok(#struct_name {
                    #(#field_assignments),*
                })
            }
        }

    };

    expanded.into()
}
