//! Proc macros for `isocline-sdk`: `strategy_entrypoint!` generates `main()`, and
//! `#[derive(ActionLabel)]` emits the label trait impl.

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

/// `strategy_entrypoint!(MyStrategy)` — generates a `main()` that builds a
/// tokio runtime, instantiates `MyStrategy::default()`, and runs the worker loop.
#[proc_macro]
pub fn strategy_entrypoint(input: TokenStream) -> TokenStream {
    let strat = parse_macro_input!(input as Path).to_token_stream();
    quote! {
        fn main() -> std::process::ExitCode {
            let rt = match ::tokio::runtime::Builder::new_current_thread().enable_all().build() {
                Ok(rt) => rt,
                Err(e) => { eprintln!("fatal: tokio runtime: {e}"); return std::process::ExitCode::from(2); }
            };
            let res = rt.block_on(async {
                let s: #strat = <#strat as ::core::default::Default>::default();
                ::isocline_sdk::runtime::run(&s).await
            });
            match res {
                Ok(()) => std::process::ExitCode::SUCCESS,
                Err(e) => { eprintln!("fatal: {e}"); std::process::ExitCode::from(1) }
            }
        }
    }.into()
}

/// `#[derive(ActionLabel)]` — `impl ActionLabel { const LABEL = "<StructName>"; }`
#[proc_macro_derive(ActionLabel)]
pub fn derive_action_label(input: TokenStream) -> TokenStream {
    let di = parse_macro_input!(input as DeriveInput);
    let ident = &di.ident;
    let label = ident.to_string();
    let (ig, tg, wc) = di.generics.split_for_impl();
    quote! {
        impl #ig ::isocline_sdk::ActionLabel for #ident #tg #wc {
            const LABEL: &'static str = #label;
        }
    }.into()
}
