use chumsky::{primitive::just, text::newline, IterParser, Parser};

use crate::{
    __internal__parse_include_str, __internal__span_macro_include_str,
    ast::{Expression, Literal, MemberAccess, StringLiteralComponent},
    parse::source_file::expression::expression,
};

use pretty_assertions::assert_eq;

#[test]
#[allow(clippy::too_many_lines)]
fn test_parse_expression() {
    __internal__span_macro_include_str!(
        crate::Span,
        "../../../../../testdata/partial/expressions.cctmpl"
    );

    assert_eq!(
        __internal__parse_include_str!(
            expression()
                .then_ignore(just(";"))
                .separated_by(newline())
                .allow_trailing()
                .collect::<Vec<Expression>>(),
            "../../../../../testdata/partial/expressions.cctmpl"
        )
        .into_result()
        .unwrap(),
        vec![
            Expression::Literal(Literal::String(vec![(
                StringLiteralComponent::Literal("Literal string"),
                s!(1..15)
            )])),
            Expression::If {
                condition: (
                    Box::new(Expression::Call {
                        func: (
                            Box::new(Expression::VariableOrCall("not_empty")),
                            s!(22..31)
                        ),
                        arguments: vec![(Expression::VariableOrCall("some_var"), s!(32..40))]
                    }),
                    s!(21..41)
                ),
                then_expression: (
                    Box::new(Expression::Literal(Literal::String(vec![]))),
                    s!(42..44)
                ),
                else_expression: None
            },
            Expression::If {
                condition: (
                    Box::new(Expression::Literal(Literal::Bool(false))),
                    s!(49..54)
                ),
                then_expression: (Box::new(Expression::Literal(Literal::Int(1))), s!(55..56)),
                else_expression: Some((Box::new(Expression::Literal(Literal::Int(0))), s!(62..63)))
            },
            Expression::MemberAccess {
                expression: (
                    Box::new(Expression::MemberAccess {
                        expression: (
                            Box::new(Expression::MemberAccess {
                                expression: (
                                    Box::new(Expression::Call {
                                        func: (
                                            Box::new(Expression::VariableOrCall("function_name")),
                                            s!(66..79)
                                        ),
                                        arguments: vec![
                                            (Expression::VariableOrCall("first_arg"), s!(80..89)),
                                            (Expression::VariableOrCall("second_arg"), s!(90..100))
                                        ]
                                    }),
                                    s!(65..101)
                                ),
                                access: (MemberAccess::Numeric(1, s!(102..103)), s!(101..103))
                            }),
                            s!(65..103)
                        ),
                        access: (MemberAccess::Named("test", s!(104..108)), s!(103..108))
                    }),
                    s!(65..108)
                ),
                access: (MemberAccess::Numeric(3, s!(109..110)), s!(108..110))
            },
            Expression::Call {
                func: (Box::new(Expression::VariableOrCall("func_1")), s!(112..118)),
                arguments: vec![
                    (Expression::VariableOrCall("arg1"), s!(119..123)),
                    (
                        Expression::Call {
                            func: (Box::new(Expression::VariableOrCall("func_2")), s!(126..132)),
                            arguments: vec![
                                (Expression::VariableOrCall("arg2"), s!(133..137)),
                                (Expression::VariableOrCall("arg3"), s!(138..142)),
                                (
                                    Expression::Call {
                                        func: (
                                            Box::new(Expression::VariableOrCall("func_3")),
                                            s!(144..150)
                                        ),
                                        arguments: vec![
                                            (Expression::VariableOrCall("arg4"), s!(151..155)),
                                            (Expression::VariableOrCall("arg5"), s!(156..160)),
                                            (Expression::VariableOrCall("arg6"), s!(163..167))
                                        ]
                                    },
                                    s!(143..168)
                                )
                            ]
                        },
                        s!(126..168)
                    )
                ]
            },
            Expression::VariableOrCall("variable_or_function_call"),
            Expression::Each {
                variable: ("person", s!(202..208)),
                array_expression: (
                    Box::new(Expression::Call {
                        func: (
                            Box::new(Expression::VariableOrCall("augment")),
                            s!(213..220)
                        ),
                        arguments: vec![(Expression::VariableOrCall("some_arr"), s!(221..229))]
                    }),
                    s!(212..230)
                ),
                body_expression: (
                    Box::new(Expression::Literal(Literal::String(vec![]))),
                    s!(231..233)
                )
            },
            Expression::Call {
                func: (
                    Box::new(Expression::VariableOrCall("function_name")),
                    s!(235..248)
                ),
                arguments: vec![
                    (Expression::Literal(Literal::String(vec![])), s!(249..251)),
                    (Expression::VariableOrCall("second_arg"), s!(252..262))
                ]
            },
            Expression::MemberAccess {
                expression: (
                    Box::new(Expression::VariableOrCall("some_tuple")),
                    s!(264..274)
                ),
                access: (MemberAccess::Numeric(0, s!(275..276)), s!(274..276))
            },
            Expression::MemberAccess {
                expression: (
                    Box::new(Expression::VariableOrCall("some_tuple")),
                    s!(278..288)
                ),
                access: (MemberAccess::Named("name", s!(289..293)), s!(288..293))
            }
        ]
    );
}
