// 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 std::fmt::{self, Display, Formatter};
use std::sync::Arc;

use datafusion::logical_expr::{
    CreateFunction, CreateFunctionBody, OperateFunctionArg, Volatility,
};
use pyo3::prelude::*;
use pyo3::IntoPyObjectExt;

use super::logical_node::LogicalNode;
use super::PyExpr;
use crate::common::data_type::PyDataType;
use crate::common::df_schema::PyDFSchema;
use crate::sql::logical::PyLogicalPlan;

#[pyclass(frozen, name = "CreateFunction", module = "datafusion.expr", subclass)]
#[derive(Clone)]
pub struct PyCreateFunction {
    create: CreateFunction,
}

impl From<PyCreateFunction> for CreateFunction {
    fn from(create: PyCreateFunction) -> Self {
        create.create
    }
}

impl From<CreateFunction> for PyCreateFunction {
    fn from(create: CreateFunction) -> PyCreateFunction {
        PyCreateFunction { create }
    }
}

impl Display for PyCreateFunction {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "CreateFunction: name {:?}", self.create.name)
    }
}

#[pyclass(
    frozen,
    name = "OperateFunctionArg",
    module = "datafusion.expr",
    subclass
)]
#[derive(Clone)]
pub struct PyOperateFunctionArg {
    arg: OperateFunctionArg,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[pyclass(frozen, eq, eq_int, name = "Volatility", module = "datafusion.expr")]
pub enum PyVolatility {
    Immutable,
    Stable,
    Volatile,
}

#[pyclass(
    frozen,
    name = "CreateFunctionBody",
    module = "datafusion.expr",
    subclass
)]
#[derive(Clone)]
pub struct PyCreateFunctionBody {
    body: CreateFunctionBody,
}

#[pymethods]
impl PyCreateFunctionBody {
    pub fn language(&self) -> Option<String> {
        self.body
            .language
            .as_ref()
            .map(|language| language.to_string())
    }

    pub fn behavior(&self) -> Option<PyVolatility> {
        self.body.behavior.as_ref().map(|behavior| match behavior {
            Volatility::Immutable => PyVolatility::Immutable,
            Volatility::Stable => PyVolatility::Stable,
            Volatility::Volatile => PyVolatility::Volatile,
        })
    }

    pub fn function_body(&self) -> Option<PyExpr> {
        self.body
            .function_body
            .as_ref()
            .map(|function_body| function_body.clone().into())
    }
}

#[pymethods]
impl PyCreateFunction {
    #[new]
    #[pyo3(signature = (or_replace, temporary, name, params, schema, return_type=None, args=None))]
    pub fn new(
        or_replace: bool,
        temporary: bool,
        name: String,
        params: PyCreateFunctionBody,
        schema: PyDFSchema,
        return_type: Option<PyDataType>,
        args: Option<Vec<PyOperateFunctionArg>>,
    ) -> Self {
        PyCreateFunction {
            create: CreateFunction {
                or_replace,
                temporary,
                name,
                args: args.map(|args| args.into_iter().map(|arg| arg.arg).collect()),
                return_type: return_type.map(|return_type| return_type.data_type),
                params: params.body,
                schema: Arc::new(schema.into()),
            },
        }
    }

    pub fn or_replace(&self) -> bool {
        self.create.or_replace
    }

    pub fn temporary(&self) -> bool {
        self.create.temporary
    }

    pub fn name(&self) -> String {
        self.create.name.clone()
    }

    pub fn params(&self) -> PyCreateFunctionBody {
        PyCreateFunctionBody {
            body: self.create.params.clone(),
        }
    }

    pub fn schema(&self) -> PyDFSchema {
        (*self.create.schema).clone().into()
    }

    pub fn return_type(&self) -> Option<PyDataType> {
        self.create
            .return_type
            .as_ref()
            .map(|return_type| return_type.clone().into())
    }

    pub fn args(&self) -> Option<Vec<PyOperateFunctionArg>> {
        self.create.args.as_ref().map(|args| {
            args.iter()
                .map(|arg| PyOperateFunctionArg { arg: arg.clone() })
                .collect()
        })
    }

    fn __repr__(&self) -> PyResult<String> {
        Ok(format!("CreateFunction({self})"))
    }

    fn __name__(&self) -> PyResult<String> {
        Ok("CreateFunction".to_string())
    }
}

impl LogicalNode for PyCreateFunction {
    fn inputs(&self) -> Vec<PyLogicalPlan> {
        vec![]
    }

    fn to_variant<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
        self.clone().into_bound_py_any(py)
    }
}
