use crate::tree::ast::expression::{Expression, FieldLookup, IndexAccess};
use crate::tree::ast::identifier::{ParsedSimpleIdentifier, SimpleIdentifier};
use crate::tree::ast::node::Span;
use crate::tree::builder::{ExpressionBuilder, IntoExpressionBuilder};
use std::rc::Rc;

/// Builder for field lookup expressions (e.g., value.field)
#[derive(Debug)]
pub struct FieldLookupBuilder {
    operand: Box<dyn ExpressionBuilder>,
    field: String,
}

impl FieldLookupBuilder {
    pub fn new(operand: impl IntoExpressionBuilder, field: &str) -> Self {
        Self {
            operand: operand.into_expression_builder(),
            field: field.to_string(),
        }
    }
}

impl ExpressionBuilder for FieldLookupBuilder {
    fn build(&self) -> Expression {
        Expression {
            span: Span::NONE,
            kind: FieldLookup {
                value: Rc::new(self.operand.build()),
                field_identifier: ParsedSimpleIdentifier::Valid(SimpleIdentifier::new(&self.field)),
            }
            .into(),
        }
    }
}

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

/// Builder for index access expressions (e.g., value[index])
#[derive(Debug)]
pub struct IndexAccessBuilder {
    operand: Box<dyn ExpressionBuilder>,
    index: Box<dyn ExpressionBuilder>,
}

impl IndexAccessBuilder {
    pub fn new(operand: impl IntoExpressionBuilder, index: impl IntoExpressionBuilder) -> Self {
        Self {
            operand: operand.into_expression_builder(),
            index: index.into_expression_builder(),
        }
    }
}

impl ExpressionBuilder for IndexAccessBuilder {
    fn build(&self) -> Expression {
        Expression {
            span: Span::NONE,
            kind: IndexAccess {
                value: Rc::new(self.operand.build()),
                index: Rc::new(self.index.build()),
            }
            .into(),
        }
    }
}

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

// Convenience functions
pub fn field(operand: impl IntoExpressionBuilder, field_name: &str) -> FieldLookupBuilder {
    FieldLookupBuilder::new(operand, field_name)
}

pub fn index(
    operand: impl IntoExpressionBuilder,
    idx: impl IntoExpressionBuilder,
) -> IndexAccessBuilder {
    IndexAccessBuilder::new(operand, idx)
}
