//! Function call expression builder

use std::sync::Arc;

use ordermap::OrderMap;

use crate::tree::ast::{
    expression::{Expression, FunctionCall},
    identifier::{ParsedSimpleIdentifier, SimpleIdentifier},
    node::Span,
};

use super::{ExpressionBuilder, IntoExpressionBuilder};

/// Builder for function calls
#[derive(Debug)]
pub struct FunctionCallBuilder {
    name: SimpleIdentifier,
    positional_args: Vec<Box<dyn ExpressionBuilder>>,
    named_args: OrderMap<String, Box<dyn ExpressionBuilder>>,
}

impl FunctionCallBuilder {
    /// Create a new function call builder with the given name
    pub fn new(name: impl Into<String>) -> Self {
        // Create SimpleIdentifier directly from the string without parsing
        let name_str = name.into();
        Self {
            name: SimpleIdentifier::new(&name_str),
            positional_args: Vec::new(),
            named_args: OrderMap::new(),
        }
    }

    /// Add a positional argument
    pub fn arg(mut self, arg: impl IntoExpressionBuilder) -> Self {
        self.positional_args.push(arg.into_expression_builder());
        self
    }

    /// Add multiple positional arguments
    pub fn args(mut self, args: impl IntoIterator<Item = impl IntoExpressionBuilder>) -> Self {
        for arg in args {
            self.positional_args.push(arg.into_expression_builder());
        }
        self
    }

    /// Add a named argument
    pub fn named_arg(mut self, name: impl Into<String>, arg: impl IntoExpressionBuilder) -> Self {
        self.named_args
            .insert(name.into(), arg.into_expression_builder());
        self
    }
}

impl ExpressionBuilder for FunctionCallBuilder {
    fn build(&self) -> Expression {
        let positional_args = self
            .positional_args
            .iter()
            .map(|arg| Arc::new(arg.build()))
            .collect();

        let named_args = self
            .named_args
            .iter()
            .map(|(name, arg)| {
                // Create ParsedSimpleIdentifier from the string
                let ident = ParsedSimpleIdentifier::Valid(SimpleIdentifier::new(name));
                (ident, Arc::new(arg.build()))
            })
            .collect();

        Expression {
            span: Span::NONE,
            kind: FunctionCall {
                name: ParsedSimpleIdentifier::Valid(self.name.clone()),
                positional_args,
                named_args,
            }
            .into(),
        }
    }
}

impl IntoExpressionBuilder for FunctionCallBuilder {
    fn into_expression_builder(self) -> Box<dyn ExpressionBuilder> {
        Box::new(self)
    }
}

// Convenience functions for common functions

/// Create a function call builder
pub fn call(name: impl Into<String>) -> FunctionCallBuilder {
    FunctionCallBuilder::new(name)
}
