use std::{collections::HashMap, str::FromStr};

use cicero_core::user::cargo_metadata;
use proc_macro2::{Span, TokenStream};
use quote::{TokenStreamExt, quote};
use syn::{Ident, Token, punctuated::{self, Punctuated}};

use crate::util;


pub(super) fn package_macro_implementation() -> TokenStream {

    let packages = cicero_core::user::CARGO_METADATA
        .workspace_packages()
        .into_iter()
        .map(|package| {
            let identifier = util::convert_string_to_identifier(&package.name);
            (identifier, package)
        })
        .collect::<HashMap<_, _>>();

    template_module_definition(&packages)
}

fn template_module_definition(packages: &HashMap<Ident, &cargo_metadata::Package>) -> TokenStream {

    let variants =
        packages.iter()
            .map(|(ident, package)| {
                let name = package.name.as_ref();
                let const_doc = format!("Meta-information for the workspace crate \"{name}\".");

                quote! {
                    #[doc = #const_doc]
                    pub const #ident: ::cicero::workspace::Package = ::cicero::workspace::Package {
                        name: #name,
                    };
                }
            })
            .collect::<TokenStream>();

    let all = packages.keys()
        .map(|ident| quote! {
            #ident,
        })
        .collect::<TokenStream>();

    let all_count = packages.keys().count();

    quote! {
        /// Meta-information about the crates/packages in your Cargo workspace.
        pub mod package {
            /// List of all crates/packages in your Cargo workspace.
            pub const ALL: [::cicero::workspace::Package; #all_count] = [
                #all
            ];

            #variants
        }
    }
}
