use proc_macro::TokenStream;
use proc_macro2::{Ident, TokenStream as TokenStream2};
use quote::{format_ident, quote};
use syn::parse_macro_input;

pub(crate) fn register_action(ident: TokenStream) -> TokenStream {
    let name = parse_macro_input!(ident as Ident);
    let registration = generate_register_action(&name);

    TokenStream::from(quote! {
        #registration
    })
}

pub(crate) fn generate_register_action(type_name: &Ident) -> TokenStream2 {
    let action_builder_fn_name = format_ident!(
        "__gpui_actions_builder_{}",
        type_name.to_string().to_lowercase()
    );

    quote! {
        impl #type_name {
            /// This is an auto generated function, do not use.
            #[automatically_derived]
            #[doc(hidden)]
            fn __autogenerated() {
                /// This is an auto generated function, do not use.
                #[doc(hidden)]
                fn #action_builder_fn_name() -> gpui::MacroActionData {
                    gpui::MacroActionData {
                        name: <#type_name as gpui::Action>::name_for_type(),
                        type_id: ::std::any::TypeId::of::<#type_name>(),
                        build: <#type_name as gpui::Action>::build,
                        json_schema: <#type_name as gpui::Action>::action_json_schema,
                        deprecated_aliases: <#type_name as gpui::Action>::deprecated_aliases(),
                        deprecation_message: <#type_name as gpui::Action>::deprecation_message(),
                        documentation: <#type_name as gpui::Action>::documentation(),
                    }
                }

                gpui::private::inventory::submit! {
                    gpui::MacroActionBuilder(#action_builder_fn_name)
                }
            }
        }
    }
}
