// 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.

use crate::planner::{ContextProvider, PlannerContext, SqlToRel};
use datafusion_common::{plan_err, DFSchema, Diagnostic, Result, Span, Spans};
use datafusion_expr::expr::{Exists, InSubquery};
use datafusion_expr::{Expr, LogicalPlan, Subquery};
use sqlparser::ast::Expr as SQLExpr;
use sqlparser::ast::{Query, SelectItem, SetExpr};
use std::sync::Arc;

impl<S: ContextProvider> SqlToRel<'_, S> {
    pub(super) fn parse_exists_subquery(
        &self,
        subquery: Query,
        negated: bool,
        input_schema: &DFSchema,
        planner_context: &mut PlannerContext,
    ) -> Result<Expr> {
        let old_outer_query_schema =
            planner_context.set_outer_query_schema(Some(input_schema.clone().into()));
        let sub_plan = self.query_to_plan(subquery, planner_context)?;
        let outer_ref_columns = sub_plan.all_out_ref_exprs();
        planner_context.set_outer_query_schema(old_outer_query_schema);
        Ok(Expr::Exists(Exists {
            subquery: Subquery {
                subquery: Arc::new(sub_plan),
                outer_ref_columns,
                spans: Spans::new(),
            },
            negated,
        }))
    }

    pub(super) fn parse_in_subquery(
        &self,
        expr: SQLExpr,
        subquery: Query,
        negated: bool,
        input_schema: &DFSchema,
        planner_context: &mut PlannerContext,
    ) -> Result<Expr> {
        let old_outer_query_schema =
            planner_context.set_outer_query_schema(Some(input_schema.clone().into()));

        let mut spans = Spans::new();
        if let SetExpr::Select(select) = &subquery.body.as_ref() {
            for item in &select.projection {
                if let SelectItem::UnnamedExpr(SQLExpr::Identifier(ident)) = item {
                    if let Some(span) = Span::try_from_sqlparser_span(ident.span) {
                        spans.add_span(span);
                    }
                }
            }
        }

        let sub_plan = self.query_to_plan(subquery, planner_context)?;
        let outer_ref_columns = sub_plan.all_out_ref_exprs();
        planner_context.set_outer_query_schema(old_outer_query_schema);

        self.validate_single_column(
            &sub_plan,
            spans.clone(),
            "Too many columns! The subquery should only return one column",
            "Select only one column in the subquery",
        )?;

        let expr_obj = self.sql_to_expr(expr, input_schema, planner_context)?;

        Ok(Expr::InSubquery(InSubquery::new(
            Box::new(expr_obj),
            Subquery {
                subquery: Arc::new(sub_plan),
                outer_ref_columns,
                spans,
            },
            negated,
        )))
    }

    pub(super) fn parse_scalar_subquery(
        &self,
        subquery: Query,
        input_schema: &DFSchema,
        planner_context: &mut PlannerContext,
    ) -> Result<Expr> {
        let old_outer_query_schema =
            planner_context.set_outer_query_schema(Some(input_schema.clone().into()));
        let mut spans = Spans::new();
        if let SetExpr::Select(select) = subquery.body.as_ref() {
            for item in &select.projection {
                if let SelectItem::ExprWithAlias { alias, .. } = item {
                    if let Some(span) = Span::try_from_sqlparser_span(alias.span) {
                        spans.add_span(span);
                    }
                }
            }
        }
        let sub_plan = self.query_to_plan(subquery, planner_context)?;
        let outer_ref_columns = sub_plan.all_out_ref_exprs();
        planner_context.set_outer_query_schema(old_outer_query_schema);

        self.validate_single_column(
            &sub_plan,
            spans.clone(),
            "Too many columns! The subquery should only return one column",
            "Select only one column in the subquery",
        )?;

        Ok(Expr::ScalarSubquery(Subquery {
            subquery: Arc::new(sub_plan),
            outer_ref_columns,
            spans,
        }))
    }

    fn validate_single_column(
        &self,
        sub_plan: &LogicalPlan,
        spans: Spans,
        error_message: &str,
        help_message: &str,
    ) -> Result<()> {
        if sub_plan.schema().fields().len() > 1 {
            let sub_schema = sub_plan.schema();
            let field_names = sub_schema.field_names();
            let diagnostic =
                self.build_multi_column_diagnostic(spans, error_message, help_message);
            plan_err!("{}: {}", error_message, field_names.join(", "); diagnostic=diagnostic)
        } else {
            Ok(())
        }
    }

    fn build_multi_column_diagnostic(
        &self,
        spans: Spans,
        error_message: &str,
        help_message: &str,
    ) -> Diagnostic {
        let full_span = Span::union_iter(spans.0.iter().cloned());
        let mut diagnostic = Diagnostic::new_error(error_message, full_span);

        for (i, span) in spans.iter().skip(1).enumerate() {
            diagnostic.add_note(format!("Extra column {}", i + 1), Some(*span));
        }

        diagnostic.add_help(help_message, None);
        diagnostic
    }
}
