extern crate proc_macro;

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

#[proc_macro_attribute]
pub fn timer(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let input = parse_macro_input!(item as ItemFn);
    let attrs = input.attrs;
    let vis = input.vis;
    let sig = input.sig;
    let fn_name = sig.ident.to_string();
    let _inputs = sig.inputs.clone();
    let _output = sig.output.clone();
    let block = input.block;

    let is_async = sig.asyncness.is_some();
    let result = if is_async {
        quote! {
            #(#attrs)* #vis #sig {
                let start = std::time::Instant::now();
                let result = async {
                    #block
                }.await;
                let duration = start.elapsed();
                println!("{} => Execution time: {:?}", #fn_name, duration);
                result
            }
        }
    } else {
        quote! {
            #(#attrs)* #vis #sig {
                let start = std::time::Instant::now();
                let result = (|| #block)();
                let duration = start.elapsed();
                println!("{} => Execution time: {:?}", #fn_name, duration);
                result
            }
        }
    };
    result.into()
}
