extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use crate::{macros::{delete::derive_delete, find_all::derive_find_all, find_one::derive_find_one, insert::derive_insert, update::derive_update}, utils::add_underscore::add_underscore};
use syn::{parse_macro_input, Data, DeriveInput, Ident};
pub fn mongo_crud_internal(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let name = ast.clone().ident;
let generics = ast.generics;
let fields = match ast.data {
Data::Struct(ref data) => data.fields.iter(),
_ => panic!("{}", "MongoCrud can only be derived for structs"),
};
let partial_fields: Vec<Ident> = fields
.clone()
.map(|f| f.ident.clone().unwrap())
.collect();
let collection_name = add_underscore(&name.to_string());
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let derived_insert = derive_insert(&name, collection_name.clone(), partial_fields.clone());
let derived_update = derive_update(&name, collection_name.clone(), partial_fields.clone());
let derived_delete = derive_delete(&name, collection_name.clone(), partial_fields.clone());
let derived_find_one = derive_find_one(&name, collection_name.clone(), partial_fields.clone());
let derived_find_all = derive_find_all(&name, collection_name.clone(), partial_fields.clone());
let created_macro = quote! {
#[async_trait::async_trait]
impl #impl_generics mongo_crud_core::MongoCrud for #name #ty_generics where Self: Send + Sync #where_clause {
#derived_insert
#derived_update
#derived_delete
#derived_find_one
#derived_find_all
}
};
TokenStream::from(created_macro)
}