//! Refactored method call transpilation with reduced complexity
//! Original complexity: 58, Target: <20 per function

use crate::backend::Transpiler;
use crate::frontend::ast::Expr;
use anyhow::{bail, Result};
use proc_macro2::TokenStream;
use quote::{quote, format_ident};

impl Transpiler {
    /// Main dispatcher for method calls (complexity: ~15)
    pub fn transpile_method_call_refactored(
        &self,
        object: &Expr,
        method: &str,
        args: &[Expr],
    ) -> Result<TokenStream> {
        let obj_tokens = self.transpile_expr(object)?;
        let arg_tokens: Result<Vec<_>> = args.iter().map(|a| self.transpile_expr(a)).collect();
        let arg_tokens = arg_tokens?;

        // Dispatch to specialized handlers based on method category
        match method {
            // Iterator methods
            "map" | "filter" | "reduce" | "fold" | "any" | "all" | "find" => 
                self.transpile_iterator_method(&obj_tokens, method, &arg_tokens),
            
            // HashMap/Dict methods
            "get" | "contains_key" | "keys" | "values" | "items" | "entry" =>
                self.transpile_hashmap_method(&obj_tokens, method, &arg_tokens),
            
            // HashSet methods
            "contains" | "union" | "intersection" | "difference" | "symmetric_difference" =>
                self.transpile_hashset_method(&obj_tokens, method, &arg_tokens),
            
            // Collection mutators
            "insert" | "remove" | "clear" | "push" | "pop" | "append" | "extend" =>
                self.transpile_collection_mutator(&obj_tokens, method, &arg_tokens),
            
            // Collection accessors
            "len" | "is_empty" | "iter" | "slice" | "first" | "last" =>
                self.transpile_collection_accessor(&obj_tokens, method, &arg_tokens),
            
            // String methods
            "to_s" | "to_string" | "to_upper" | "to_lower" | "length" | 
            "trim" | "split" | "replace" | "starts_with" | "ends_with" =>
                self.transpile_string_method(&obj_tokens, method, &arg_tokens),
            
            // DataFrame methods
            "select" | "groupby" | "agg" | "sort" | "mean" | "std" | "min" | "max" |
            "sum" | "count" | "drop_nulls" | "fill_null" | "pivot" | "melt" | 
            "head" | "tail" | "sample" | "describe" =>
                self.transpile_dataframe_method_refactored(&obj_tokens, method, &arg_tokens),
            
            // Default: pass through
            _ => {
                let method_ident = format_ident!("{}", method);
                Ok(quote! { #obj_tokens.#method_ident(#(#arg_tokens),*) })
            }
        }
    }
    
    /// Handle iterator methods (complexity: ~10)
    fn transpile_iterator_method(
        &self,
        obj: &TokenStream,
        method: &str,
        args: &[TokenStream],
    ) -> Result<TokenStream> {
        match method {
            "map" => Ok(quote! { #obj.iter().map(#(#args),*).collect::<Vec<_>>() }),
            "filter" => Ok(quote! { #obj.into_iter().filter(#(#args),*).collect::<Vec<_>>() }),
            "reduce" => Ok(quote! { #obj.into_iter().reduce(#(#args),*) }),
            "fold" => {
                if args.len() != 2 {
                    bail!("fold requires exactly 2 arguments");
                }
                let init = &args[0];
                let func = &args[1];
                Ok(quote! { #obj.into_iter().fold(#init, #func) })
            }
            "any" => Ok(quote! { #obj.iter().any(#(#args),*) }),
            "all" => Ok(quote! { #obj.iter().all(#(#args),*) }),
            "find" => Ok(quote! { #obj.iter().find(#(#args),*).cloned() }),
            _ => unreachable!("Unknown iterator method: {}", method),
        }
    }
    
    /// Handle HashMap/Dict methods (complexity: ~10)
    fn transpile_hashmap_method(
        &self,
        obj: &TokenStream,
        method: &str,
        args: &[TokenStream],
    ) -> Result<TokenStream> {
        let method_ident = format_ident!("{}", method);
        match method {
            "get" => Ok(quote! { #obj.#method_ident(#(#args),*).cloned() }),
            "items" => Ok(quote! { #obj.iter().map(|(k, v)| (k.clone(), v.clone())) }),
            "contains_key" | "keys" | "values" | "entry" => 
                Ok(quote! { #obj.#method_ident(#(#args),*) }),
            _ => unreachable!("Unknown HashMap method: {}", method),
        }
    }
    
    /// Handle HashSet methods (complexity: ~12)
    fn transpile_hashset_method(
        &self,
        obj: &TokenStream,
        method: &str,
        args: &[TokenStream],
    ) -> Result<TokenStream> {
        match method {
            "contains" => {
                let method_ident = format_ident!("{}", method);
                Ok(quote! { #obj.#method_ident(#(#args),*) })
            }
            "union" | "intersection" | "difference" | "symmetric_difference" => {
                if args.len() != 1 {
                    bail!("{} requires exactly 1 argument", method);
                }
                let other = &args[0];
                let method_ident = format_ident!("{}", method);
                Ok(quote! { 
                    {
                        use std::collections::HashSet;
                        #obj.#method_ident(&#other).cloned().collect::<HashSet<_>>()
                    }
                })
            }
            _ => unreachable!("Unknown HashSet method: {}", method),
        }
    }
    
    /// Handle collection mutator methods (complexity: ~5)
    fn transpile_collection_mutator(
        &self,
        obj: &TokenStream,
        method: &str,
        args: &[TokenStream],
    ) -> Result<TokenStream> {
        let method_ident = format_ident!("{}", method);
        Ok(quote! { #obj.#method_ident(#(#args),*) })
    }
    
    /// Handle collection accessor methods (complexity: ~10)
    fn transpile_collection_accessor(
        &self,
        obj: &TokenStream,
        method: &str,
        args: &[TokenStream],
    ) -> Result<TokenStream> {
        match method {
            "slice" => {
                if args.len() != 2 {
                    bail!("slice requires exactly 2 arguments");
                }
                let start = &args[0];
                let end = &args[1];
                Ok(quote! { #obj[#start..#end].to_vec() })
            }
            "first" => Ok(quote! { #obj.first().cloned() }),
            "last" => Ok(quote! { #obj.last().cloned() }),
            _ => {
                let method_ident = format_ident!("{}", method);
                Ok(quote! { #obj.#method_ident(#(#args),*) })
            }
        }
    }
    
    /// Handle string methods (complexity: ~12)
    fn transpile_string_method(
        &self,
        obj: &TokenStream,
        method: &str,
        args: &[TokenStream],
    ) -> Result<TokenStream> {
        match method {
            "to_s" | "to_string" => Ok(quote! { #obj }),
            "to_upper" => Ok(quote! { #obj.to_uppercase(#(#args),*) }),
            "to_lower" => Ok(quote! { #obj.to_lowercase(#(#args),*) }),
            "length" => Ok(quote! { #obj.len(#(#args),*) }),
            "trim" => Ok(quote! { #obj.trim(#(#args),*).to_string() }),
            "split" => {
                if args.is_empty() {
                    Ok(quote! { #obj.split_whitespace().map(String::from).collect::<Vec<_>>() })
                } else {
                    Ok(quote! { #obj.split(#(#args),*).map(String::from).collect::<Vec<_>>() })
                }
            }
            "replace" => {
                if args.len() != 2 {
                    bail!("replace requires exactly 2 arguments");
                }
                Ok(quote! { #obj.replace(#(#args),*) })
            }
            "starts_with" | "ends_with" => {
                let method_ident = format_ident!("{}", method);
                Ok(quote! { #obj.#method_ident(#(#args),*) })
            }
            _ => unreachable!("Unknown string method: {}", method),
        }
    }
    
    /// Handle DataFrame methods (complexity: ~5)
    fn transpile_dataframe_method_refactored(
        &self,
        obj: &TokenStream,
        method: &str,
        args: &[TokenStream],
    ) -> Result<TokenStream> {
        let method_ident = format_ident!("{}", method);
        Ok(quote! { #obj.#method_ident(#(#args),*) })
    }
}