use std::error::Error;

use crate::{Datum, Expr, FnArgs, InfixOp};

#[test]
fn parses_without_args() -> Result<(), Box<dyn Error>> {
    assert_eq!(
        Expr::try_from("now()")?,
        Expr::FnCall {
            name: vec!["now".to_owned()],
            args: FnArgs::Exprs {
                distinct_flag: false,
                exprs: vec![],
            },
        }
    );
    Ok(())
}

#[test]
fn parses_with_args() -> Result<(), Box<dyn Error>> {
    assert_eq!(
        Expr::try_from("repeat('hello!', 1 + 2)")?,
        Expr::FnCall {
            name: vec!["repeat".to_owned()],
            args: FnArgs::Exprs {
                distinct_flag: false,
                exprs: vec![
                    Expr::Literal(Datum::Text(Some("hello!".to_owned()))),
                    Expr::Infix {
                        lhs: Box::new(Expr::Literal(Datum::Numeric(Some(1.into())))),
                        op: InfixOp::Add,
                        rhs: Box::new(Expr::Literal(Datum::Numeric(Some(2.into())))),
                    }
                ],
            },
        }
    );
    Ok(())
}

#[test]
fn schema_qualified() -> Result<(), Box<dyn Error>> {
    assert_eq!(
        Expr::try_from(r#"my_schema."MyFunc"('hello!', 1)"#)?,
        Expr::FnCall {
            name: vec!["my_schema".to_owned(), "MyFunc".to_owned()],
            args: FnArgs::Exprs {
                distinct_flag: false,
                exprs: vec![
                    Expr::Literal(Datum::Text(Some("hello!".to_owned()))),
                    Expr::Literal(Datum::Numeric(Some(1.into()))),
                ],
            },
        }
    );
    Ok(())
}

#[test]
fn distinct_aggregate() -> Result<(), Box<dyn Error>> {
    assert_eq!(
        Expr::try_from(r#"AGGREGATOR(DISTINCT a."Col 1", b."Col 2")"#)?,
        Expr::FnCall {
            name: vec!["aggregator".to_owned()],
            args: FnArgs::Exprs {
                distinct_flag: true,
                exprs: vec![
                    Expr::ObjName(vec!["a".to_owned(), "Col 1".to_owned()]),
                    Expr::ObjName(vec!["b".to_owned(), "Col 2".to_owned()]),
                ],
            },
        }
    );
    Ok(())
}
