// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! Test the ability for dialects to override parsing

use sqlparser::{
    ast::{BinaryOperator, CommitStatement, Expr, Statement, Value},
    dialect::Dialect,
    keywords::Keyword,
    parser::{Parser, ParserError},
    test_utils::{expr_from_projection, only},
    tokenizer::Token,
};

#[test]
fn custom_prefix_parser() -> Result<(), ParserError> {
    #[derive(Debug)]
    struct MyDialect {}

    impl Dialect for MyDialect {
        fn is_identifier_start(&self, ch: char) -> bool {
            is_identifier_start(ch)
        }

        fn is_identifier_part(&self, ch: char) -> bool {
            is_identifier_part(ch)
        }

        fn parse_prefix(&self, parser: &mut Parser) -> Option<Result<Expr, ParserError>> {
            if parser.consume_token(&Token::Number("1".to_string(), false)) {
                Some(Ok(Expr::Value(Value::Null.with_empty_span())))
            } else {
                None
            }
        }
    }

    let dialect = MyDialect {};
    let sql = "SELECT 1 + 2";
    let ast = Parser::parse_sql(&dialect, sql)?;
    let query = &ast[0];
    assert_eq!("SELECT NULL + 2", &format!("{query}"));
    Ok(())
}

#[test]
fn custom_infix_parser() -> Result<(), ParserError> {
    #[derive(Debug)]
    struct MyDialect {}

    impl Dialect for MyDialect {
        fn is_identifier_start(&self, ch: char) -> bool {
            is_identifier_start(ch)
        }

        fn is_identifier_part(&self, ch: char) -> bool {
            is_identifier_part(ch)
        }

        fn parse_infix(
            &self,
            parser: &mut Parser,
            expr: &Expr,
            _precedence: u8,
        ) -> Option<Result<Expr, ParserError>> {
            if parser.consume_token(&Token::Plus) {
                Some(Ok(Expr::BinaryOp {
                    left: Box::new(expr.clone()),
                    op: BinaryOperator::Multiply, // translate Plus to Multiply
                    right: Box::new(parser.parse_expr().unwrap()),
                }))
            } else {
                None
            }
        }
    }

    let dialect = MyDialect {};
    let sql = "SELECT 1 + 2";
    let ast = Parser::parse_sql(&dialect, sql)?;
    let query = &ast[0];
    assert_eq!("SELECT 1 * 2", &format!("{query}"));
    Ok(())
}

#[test]
fn custom_statement_parser() -> Result<(), ParserError> {
    #[derive(Debug)]
    struct MyDialect {}

    impl Dialect for MyDialect {
        fn is_identifier_start(&self, ch: char) -> bool {
            is_identifier_start(ch)
        }

        fn is_identifier_part(&self, ch: char) -> bool {
            is_identifier_part(ch)
        }

        fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
            if parser.parse_keyword(Keyword::SELECT) {
                for _ in 0..3 {
                    let _ = parser.next_token();
                }
                Some(Ok(Statement::Commit(
                    CommitStatement {
                        chain: false,
                        end: false,
                        modifier: None,
                    }
                    .into(),
                )))
            } else {
                None
            }
        }
    }

    let dialect = MyDialect {};
    let sql = "SELECT 1 + 2";
    let ast = Parser::parse_sql(&dialect, sql)?;
    let query = &ast[0];
    assert_eq!("COMMIT", &format!("{query}"));
    Ok(())
}

#[test]
fn test_map_syntax_not_support_default() -> Result<(), ParserError> {
    #[derive(Debug)]
    struct MyDialect {}

    impl Dialect for MyDialect {
        fn is_identifier_start(&self, ch: char) -> bool {
            is_identifier_start(ch)
        }

        fn is_identifier_part(&self, ch: char) -> bool {
            is_identifier_part(ch)
        }
    }

    let dialect = MyDialect {};
    let sql = "SELECT MAP {1: 2}";
    let ast = Parser::parse_sql(&dialect, sql);
    assert!(ast.is_err());
    Ok(())
}

fn is_identifier_start(ch: char) -> bool {
    ch.is_ascii_lowercase() || ch.is_ascii_uppercase() || ch == '_'
}

fn is_identifier_part(ch: char) -> bool {
    ch.is_ascii_lowercase()
        || ch.is_ascii_uppercase()
        || ch.is_ascii_digit()
        || ch == '$'
        || ch == '_'
}

#[test]
fn custom_dialect_lambda_keyword_syntax_without_arrow() {
    // A dialect that gives `->` its own meaning can still support lambdas
    // through the `LAMBDA` keyword spelling.
    #[derive(Debug)]
    struct MyDialect {}

    impl Dialect for MyDialect {
        fn is_identifier_start(&self, ch: char) -> bool {
            is_identifier_start(ch)
        }

        fn is_identifier_part(&self, ch: char) -> bool {
            is_identifier_part(ch)
        }

        fn supports_lambda_keyword_syntax(&self) -> bool {
            true
        }
    }

    let dialect = MyDialect {};

    // The `LAMBDA` spelling parses.
    let sql = "SELECT transform(xs, lambda x : x + 1)";
    assert_eq!(
        sql,
        &format!("{}", Parser::parse_sql(&dialect, sql).unwrap()[0])
    );

    // `->` keeps whatever meaning the dialect gives it, rather than
    // introducing a lambda parameter.
    let sql = "SELECT a -> 'b'";
    let ast = Parser::parse_sql(&dialect, sql).unwrap();
    match &ast[0] {
        Statement::Query(query) => {
            let Expr::BinaryOp { op, .. } =
                expr_from_projection(only(&query.body.as_select().unwrap().projection))
            else {
                panic!("expected `->` to stay a binary operator");
            };
            assert_eq!(&BinaryOperator::Arrow, op);
        }
        stmt => panic!("unexpected statement {stmt}"),
    }
}

#[test]
fn custom_dialect_lambda_keyword_defaults_to_arrow_support() {
    // Dialects that opt into the `->` spelling get the `LAMBDA` spelling too,
    // so the new capability does not change any existing dialect.
    #[derive(Debug)]
    struct MyDialect {}

    impl Dialect for MyDialect {
        fn is_identifier_start(&self, ch: char) -> bool {
            is_identifier_start(ch)
        }

        fn is_identifier_part(&self, ch: char) -> bool {
            is_identifier_part(ch)
        }

        fn supports_lambda_functions(&self) -> bool {
            true
        }
    }

    let dialect = MyDialect {};
    assert!(dialect.supports_lambda_keyword_syntax());
    for sql in [
        "SELECT transform(xs, lambda x : x + 1)",
        "SELECT transform(xs, x -> x + 1)",
    ] {
        assert_eq!(
            sql,
            &format!("{}", Parser::parse_sql(&dialect, sql).unwrap()[0])
        );
    }
}

#[test]
fn custom_dialect_lambda_arrow_syntax_without_keyword() {
    // Arrow lambdas stay on while the `LAMBDA` keyword spelling is off,
    // as in engines like Spark and Snowflake.
    #[derive(Debug)]
    struct MyDialect {}

    impl Dialect for MyDialect {
        fn is_identifier_start(&self, ch: char) -> bool {
            is_identifier_start(ch)
        }

        fn is_identifier_part(&self, ch: char) -> bool {
            is_identifier_part(ch)
        }

        fn supports_lambda_functions(&self) -> bool {
            true
        }

        fn supports_lambda_keyword_syntax(&self) -> bool {
            false
        }
    }

    let dialect = MyDialect {};

    let sql = "SELECT transform(xs, x -> x + 1)";
    assert_eq!(
        sql,
        &format!("{}", Parser::parse_sql(&dialect, sql).unwrap()[0])
    );
    assert!(Parser::parse_sql(&dialect, "SELECT transform(xs, lambda x : x + 1)").is_err());
}
