// 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::future::Future;
use std::ptr::NonNull;
use std::sync::{Arc, OnceLock};
use std::time::Duration;

use datafusion::datasource::TableProvider;
use datafusion::execution::TaskContext;
use datafusion::execution::context::SessionContext;
use datafusion::logical_expr::Volatility;
use datafusion::physical_optimizer::PhysicalOptimizerRule;
use datafusion_ffi::execution::FFI_TaskContextProvider;
use datafusion_ffi::physical_optimizer::FFI_PhysicalOptimizerRule;
use datafusion_ffi::proto::logical_extension_codec::FFI_LogicalExtensionCodec;
use datafusion_ffi::proto::physical_extension_codec::FFI_PhysicalExtensionCodec;
use datafusion_ffi::query_planner::FFI_QueryPlanner;
use datafusion_ffi::table_provider::FFI_TableProvider;
use pyo3::exceptions::{PyImportError, PyTypeError, PyValueError};
use pyo3::prelude::*;
use pyo3::types::{PyCapsule, PyType};
use tokio::runtime::Runtime;
use tokio::task::JoinHandle;
use tokio::time::sleep;

pub mod errors;
pub use crate::errors::to_datafusion_err;
use crate::errors::{PyDataFusionError, PyDataFusionResult};

/// Utility to get the Tokio Runtime from Python
#[inline]
pub fn get_tokio_runtime() -> &'static Runtime {
    // NOTE: Other pyo3 python libraries have had issues with using tokio
    // behind a forking app-server like `gunicorn`
    // If we run into that problem, in the future we can look to `delta-rs`
    // which adds a check in that disallows calls from a forked process
    // https://github.com/delta-io/delta-rs/blob/87010461cfe01563d91a4b9cd6fa468e2ad5f283/python/src/utils.rs#L10-L31
    static RUNTIME: OnceLock<Runtime> = OnceLock::new();
    RUNTIME.get_or_init(|| Runtime::new().unwrap())
}

#[inline]
pub fn is_ipython_env(py: Python) -> &'static bool {
    static IS_IPYTHON_ENV: OnceLock<bool> = OnceLock::new();
    IS_IPYTHON_ENV.get_or_init(|| {
        py.import("IPython")
            .and_then(|ipython| ipython.call_method0("get_ipython"))
            .map(|ipython| !ipython.is_none())
            .unwrap_or(false)
    })
}

/// Utility to get the Global Datafussion CTX
#[inline]
pub fn get_global_ctx() -> &'static Arc<SessionContext> {
    static CTX: OnceLock<Arc<SessionContext>> = OnceLock::new();
    CTX.get_or_init(|| Arc::new(SessionContext::new()))
}

/// Utility to collect rust futures with GIL released and respond to
/// Python interrupts such as ``KeyboardInterrupt``. If a signal is
/// received while the future is running, the future is aborted and the
/// corresponding Python exception is raised.
pub fn wait_for_future<F>(py: Python, fut: F) -> PyResult<F::Output>
where
    F: Future + Send,
    F::Output: Send,
{
    let runtime: &Runtime = get_tokio_runtime();
    const INTERVAL_CHECK_SIGNALS: Duration = Duration::from_millis(1_000);

    // Some fast running processes that generate many `wait_for_future` calls like
    // PartitionedDataFrameStreamReader::next require checking for interrupts early
    py.run(cr"pass", None, None)?;
    py.check_signals()?;

    py.detach(|| {
        runtime.block_on(async {
            tokio::pin!(fut);
            loop {
                tokio::select! {
                    res = &mut fut => break Ok(res),
                    _ = sleep(INTERVAL_CHECK_SIGNALS) => {
                        Python::attach(|py| {
                                // Execute a no-op Python statement to trigger signal processing.
                                // This is necessary because py.check_signals() alone doesn't
                                // actually check for signals - it only raises an exception if
                                // a signal was already set during a previous Python API call.
                                // Running even trivial Python code forces the interpreter to
                                // process any pending signals (like KeyboardInterrupt).
                                py.run(cr"pass", None, None)?;
                                py.check_signals()
                        })?;
                    }
                }
            }
        })
    })
}

/// Spawn a [`Future`] on the Tokio runtime and wait for completion
/// while respecting Python signal handling.
pub fn spawn_future<F, T>(py: Python, fut: F) -> PyDataFusionResult<T>
where
    F: Future<Output = datafusion::common::Result<T>> + Send + 'static,
    T: Send + 'static,
{
    let rt = get_tokio_runtime();
    let handle: JoinHandle<datafusion::common::Result<T>> = rt.spawn(fut);
    // Wait for the join handle while respecting Python signal handling.
    // We handle errors in two steps so `?` maps the error types correctly:
    // 1) convert any Python-related error from `wait_for_future` into `PyDataFusionError`
    // 2) convert any DataFusion error (inner result) into `PyDataFusionError`
    let inner_result = wait_for_future(py, async {
        // handle.await yields `Result<datafusion::common::Result<T>, JoinError>`
        // map JoinError into a DataFusion error so the async block returns
        // `datafusion::common::Result<T>` (i.e. Result<T, DataFusionError>)
        match handle.await {
            Ok(inner) => inner,
            Err(join_err) => Err(to_datafusion_err(join_err)),
        }
    })?; // converts PyErr -> PyDataFusionError

    // `inner_result` is `datafusion::common::Result<T>`; use `?` to convert
    // the inner DataFusion error into `PyDataFusionError` via `From` and
    // return the inner `T` on success.
    Ok(inner_result?)
}

pub fn parse_volatility(value: &str) -> PyDataFusionResult<Volatility> {
    Ok(match value {
        "immutable" => Volatility::Immutable,
        "stable" => Volatility::Stable,
        "volatile" => Volatility::Volatile,
        value => {
            return Err(PyDataFusionError::Common(format!(
                "Unsupported volatility type: `{value}`, supported \
                 values are: immutable, stable and volatile."
            )));
        }
    })
}

/// Check that `capsule` carries the name `name`, and say so usefully if not.
///
/// This looks redundant next to `capsule.pointer_checked(Some(name))`, which
/// also rejects a mismatched name, and it is not. `pointer_checked` bottoms out
/// in CPython's `PyCapsule_GetPointer`, whose error is the fixed string
/// `PyCapsule_GetPointer called with incorrect name` — it names neither what
/// was expected nor what was found. Handing an extension author that message
/// tells them nothing about which capsule they got wrong.
///
/// So call this first at every extraction site. `pointer_checked` still gets
/// the name, because it is what actually guards the cast.
pub fn validate_pycapsule(capsule: &Bound<PyCapsule>, name: &str) -> PyResult<()> {
    let capsule_name = capsule.name()?;
    if capsule_name.is_none() {
        return Err(PyValueError::new_err(format!(
            "Expected {name} PyCapsule to have name set."
        )));
    }

    let capsule_name = unsafe { capsule_name.unwrap().as_cstr().to_str() }
        .map_err(|err| PyValueError::new_err(err.to_string()))?;
    if capsule_name != name {
        return Err(PyValueError::new_err(format!(
            "Expected name '{name}' in PyCapsule, instead got '{capsule_name}'"
        )));
    }

    Ok(())
}

/// Reject an FFI struct built against a different major version of
/// `datafusion-ffi`.
///
/// `found` comes from the struct's own `version` function pointer, which
/// reports the major version of the library that produced it.
///
/// This is a diagnostic, not a soundness guarantee. Reading `version` out of
/// the struct already assumes the local field layout, and `version` is not the
/// first field on any of these types, so a sufficiently different layout can
/// fault before this ever runs. What it buys is a clear error for the case that
/// actually happens -- an extension library compiled against a different
/// DataFusion -- rather than undefined behaviour on first use, which is what
/// `datafusion_ffi::version` exists for.
///
/// Not every FFI type carries a version. `FFI_TaskContextProvider`,
/// `FFI_TableProviderFactory`, and `FFI_ExtensionOptions` have no such field,
/// so their importers cannot check and are not expected to.
///
/// # If the FFI ABI stabilizes
///
/// Exact equality is the right test only while `datafusion_ffi::version`
/// tracks the DataFusion crate's semver major, which it does today
/// (`env!("CARGO_PKG_VERSION")`, `.major`). That number therefore moves on
/// every major release whether or not the ABI actually changed.
///
/// Should a version span become compatible, **this function body is the only
/// thing to change** -- callers pass a `found` value and no policy. Relaxing it
/// at a call site instead would reintroduce the split this helper exists to
/// remove.
///
/// The likelier fix is upstream, not here: if the ABI is stable but `version`
/// still follows the crate major, upstream's own compatibility marker is wrong
/// for every consumer, not just this one. Prefer waiting for
/// `datafusion_ffi::version` to reflect the real ABI over inventing a range
/// policy locally.
pub fn check_ffi_version(kind: &str, found: u64) -> PyResult<()> {
    let expected = datafusion_ffi::version();
    if found != expected {
        return Err(PyImportError::new_err(format!(
            "Incompatible DataFusion {kind} major version {found}; expected {expected}. \
             Rebuild the library providing this object against a matching DataFusion."
        )));
    }
    Ok(())
}

pub fn table_provider_from_pycapsule<'py>(
    mut obj: Bound<'py, PyAny>,
    session: Bound<'py, PyAny>,
) -> PyResult<Option<Arc<dyn TableProvider>>> {
    obj = call_capsule_getter(obj, "__datafusion_table_provider__", Some(&session))?;

    if let Ok(capsule) = obj.cast::<PyCapsule>() {
        validate_pycapsule(capsule, "datafusion_table_provider")?;
        let data: NonNull<FFI_TableProvider> = capsule
            .pointer_checked(Some(c"datafusion_table_provider"))?
            .cast();
        let provider = unsafe { data.as_ref() };
        check_ffi_version("table provider", unsafe { (provider.version)() })?;
        let provider: Arc<dyn TableProvider> = provider.into();

        Ok(Some(provider))
    } else {
        Ok(None)
    }
}

pub fn create_logical_extension_capsule<'py>(
    py: Python<'py>,
    codec: &FFI_LogicalExtensionCodec,
) -> PyResult<Bound<'py, PyCapsule>> {
    let codec = codec.clone();

    PyCapsule::new_with_value(py, codec, cr"datafusion_logical_extension_codec")
}

/// The single positional argument datafusion-python hands a capsule getter.
///
/// Carrying the argument and its description together is what lets one
/// diagnostic serve the whole family: the getters do not all take a session,
/// and telling the author of a catalog provider that their method "must accept
/// the SessionContext" would send them to fix the wrong signature.
#[derive(Clone, Copy)]
pub enum CapsuleGetterArg<'a, 'py> {
    /// The getter takes no arguments, so it cannot refuse one. A `TypeError`
    /// from one of these is always the getter's own and is never rewritten.
    None,
    /// The `SessionContext` the object is being installed on.
    Session(&'a Bound<'py, PyAny>),
    /// The host's logical extension codec, as a
    /// `datafusion_logical_extension_codec` capsule.
    LogicalCodec(&'a Bound<'py, PyAny>),
}

impl<'a, 'py> CapsuleGetterArg<'a, 'py> {
    fn value(self) -> Option<&'a Bound<'py, PyAny>> {
        match self {
            Self::None => None,
            Self::Session(value) | Self::LogicalCodec(value) => Some(value),
        }
    }

    fn expected(self) -> &'static str {
        match self {
            Self::None => "",
            Self::Session(_) => "the SessionContext it is being installed on",
            Self::LogicalCodec(_) => "the host's logical extension codec",
        }
    }
}

impl<'a, 'py> From<Option<&'a Bound<'py, PyAny>>> for CapsuleGetterArg<'a, 'py> {
    fn from(session: Option<&'a Bound<'py, PyAny>>) -> Self {
        session.map_or(Self::None, Self::Session)
    }
}

/// Calls `obj.__<attr_name>__(arg)`, or `obj.__<attr_name>__()` for
/// [`CapsuleGetterArg::None`]. Returns `obj` untouched when it has no such
/// attribute, so a raw capsule passes straight through.
///
/// **Every** capsule getter goes through here rather than calling `getattr`
/// directly, so that the mapping from a refused argument to a useful error
/// lives in one place. Three importers previously each had their own copy and
/// each missed later corrections to it; the getters that take no argument route
/// through as well, so the rule has no exceptions to remember.
pub fn call_capsule_getter<'a, 'py: 'a>(
    obj: Bound<'py, PyAny>,
    attr_name: &str,
    arg: impl Into<CapsuleGetterArg<'a, 'py>>,
) -> PyResult<Bound<'py, PyAny>> {
    if !obj.hasattr(attr_name)? {
        return Ok(obj);
    }

    let arg = arg.into();
    let getter = obj.getattr(attr_name)?;
    let result = match arg.value() {
        Some(value) => getter.call1((value,)),
        None => getter.call0(),
    };

    result.map_err(|err| {
        let py = obj.py();
        if arg.value().is_none() || !err.get_type(py).is(PyType::new::<PyTypeError>(py)) {
            return err;
        }

        // Not every `TypeError` here means the getter refused the argument. One
        // raised *inside* a correctly-signed getter would otherwise be reported
        // as a version mismatch, sending an extension author to upgrade a
        // library that is already correct.
        //
        // The two are distinguishable: an arity mismatch is raised by the call
        // machinery before the getter's frame exists, so nothing unwinds and no
        // traceback is attached. An error from the body unwinds that frame and
        // carries one.
        //
        // This holds because the call originates in Rust. `call1` pushes no
        // Python caller frame, so an arity error has nothing to unwind and
        // arrives bare. If a Python-level shim is ever interposed between the
        // host and the getter, its frame would supply a traceback and this
        // check would quietly stop firing -- the diagnostic would degrade to
        // the bare `TypeError` it exists to replace, with no test failing.
        if err.traceback(py).is_some() {
            return err;
        }

        let import_err = PyImportError::new_err(format!(
            "Incompatible libraries. `{attr_name}` must accept {}. \
             Upgrade the library providing this object.",
            arg.expected()
        ));
        // Keep the original reachable as `__cause__` rather than discarding it.
        import_err.set_cause(py, Some(err));
        import_err
    })
}

pub fn ffi_logical_codec_from_pycapsule<'py>(
    obj: Bound<'py, PyAny>,
    session: Option<&Bound<'py, PyAny>>,
) -> PyResult<FFI_LogicalExtensionCodec> {
    let capsule = call_capsule_getter(obj, "__datafusion_logical_extension_codec__", session)?;

    let capsule = capsule.cast::<PyCapsule>()?;
    validate_pycapsule(capsule, "datafusion_logical_extension_codec")?;
    let data: NonNull<FFI_LogicalExtensionCodec> = capsule
        .pointer_checked(Some(c"datafusion_logical_extension_codec"))?
        .cast();
    let codec = unsafe { data.as_ref() };
    check_ffi_version("logical extension codec", unsafe { (codec.version)() })?;

    Ok(codec.clone())
}

pub fn ffi_physical_codec_from_pycapsule<'py>(
    obj: Bound<'py, PyAny>,
    session: Option<&Bound<'py, PyAny>>,
) -> PyResult<FFI_PhysicalExtensionCodec> {
    let capsule = call_capsule_getter(obj, "__datafusion_physical_extension_codec__", session)?;

    let capsule = capsule.cast::<PyCapsule>()?;
    validate_pycapsule(capsule, "datafusion_physical_extension_codec")?;
    let data: NonNull<FFI_PhysicalExtensionCodec> = capsule
        .pointer_checked(Some(c"datafusion_physical_extension_codec"))?
        .cast();
    let codec = unsafe { data.as_ref() };
    check_ffi_version("physical extension codec", unsafe { (codec.version)() })?;

    Ok(codec.clone())
}

/// Extracts the `FFI_TaskContextProvider` a session exposes.
///
/// An extension library exporting a codec needs one for the decode callbacks
/// its codec will receive. Taking the host's means those callbacks resolve
/// names against the session that is actually running the query, and removes
/// any need for the library to construct a `SessionContext` of its own.
pub fn ffi_task_context_provider_from_pycapsule(
    session: &Bound<PyAny>,
) -> PyResult<FFI_TaskContextProvider> {
    let capsule = call_capsule_getter(
        session.clone(),
        "__datafusion_task_context_provider__",
        CapsuleGetterArg::None,
    )?;

    let capsule = capsule.cast::<PyCapsule>()?;
    validate_pycapsule(capsule, "datafusion_task_context_provider")?;
    let data: NonNull<FFI_TaskContextProvider> = capsule
        .pointer_checked(Some(c"datafusion_task_context_provider"))?
        .cast();
    let provider = unsafe { data.as_ref() };

    Ok(provider.clone())
}

pub fn create_query_planner_capsule<'py>(
    py: Python<'py>,
    planner: &FFI_QueryPlanner,
) -> PyResult<Bound<'py, PyCapsule>> {
    PyCapsule::new_with_value(py, planner.clone(), cr"datafusion_query_planner")
}

pub fn ffi_query_planner_from_pycapsule<'py>(
    obj: &Bound<'py, PyAny>,
    session: Option<&Bound<'py, PyAny>>,
) -> PyResult<FFI_QueryPlanner> {
    let capsule = call_capsule_getter(obj.clone(), "__datafusion_query_planner__", session)?;

    let capsule = capsule.cast::<PyCapsule>()?;
    validate_pycapsule(capsule, "datafusion_query_planner")?;
    let data: NonNull<FFI_QueryPlanner> = capsule
        .pointer_checked(Some(c"datafusion_query_planner"))?
        .cast();
    let planner = unsafe { data.as_ref() };
    check_ffi_version("query planner", unsafe { (planner.version)() })?;

    Ok(planner.clone())
}

pub fn create_physical_extension_capsule<'py>(
    py: Python<'py>,
    codec: &FFI_PhysicalExtensionCodec,
) -> PyResult<Bound<'py, PyCapsule>> {
    let codec = codec.clone();

    PyCapsule::new_with_value(py, codec, cr"datafusion_physical_extension_codec")
}

/// Define a `<fn_name>(obj) -> PyResult<Arc<$output_type>>` extractor that
/// accepts either a raw `PyCapsule` carrying `$ffi_type` or any object
/// exposing `__<capsule_name>__()` that returns one.
///
/// Use this when `Arc<$output_type>: From<&$ffi_type>` (infallible
/// conversion). For fallible conversions use [`try_from_pycapsule!`]
/// instead.
///
/// The generated extractor does not check the FFI major version, because not
/// every FFI type carries one. If `$ffi_type` has a `version` field, call
/// [`check_ffi_version`] on it yourself, as the hand-written extractors in this
/// crate do.
#[macro_export]
macro_rules! from_pycapsule {
    ($fn_name:ident, $capsule_name:literal, $ffi_type:ty, $output_type:ty) => {
        pub fn $fn_name(
            obj: &$crate::pyo3::Bound<$crate::pyo3::PyAny>,
        ) -> $crate::pyo3::PyResult<std::sync::Arc<$output_type>> {
            use $crate::pyo3::prelude::*;
            use $crate::pyo3::types::PyCapsule;

            let obj = $crate::call_capsule_getter(
                obj.clone(),
                concat!("__", $capsule_name, "__"),
                $crate::CapsuleGetterArg::None,
            )?;
            let capsule = obj.cast::<PyCapsule>().map_err(|_| {
                $crate::errors::py_datafusion_err(concat!(
                    "Invalid ",
                    $capsule_name,
                    ". Does not contain PyCapsule object."
                ))
            })?;
            $crate::validate_pycapsule(&capsule, $capsule_name)?;

            let expected_name = std::ffi::CString::new($capsule_name)
                .expect("capsule name must not contain interior NUL bytes");
            let data: std::ptr::NonNull<$ffi_type> = capsule
                .pointer_checked(Some(expected_name.as_c_str()))?
                .cast();
            let output_obj = unsafe { data.as_ref() };
            let output_obj: std::sync::Arc<$output_type> = output_obj.into();

            Ok(output_obj)
        }
    };
}

/// Same shape as [`from_pycapsule!`] but for FFI types whose conversion
/// into `Arc<$output_type>` is fallible (uses `TryFrom`).
#[macro_export]
macro_rules! try_from_pycapsule {
    ($fn_name:ident, $capsule_name:literal, $ffi_type:ty, $output_type:ty) => {
        pub fn $fn_name(
            obj: &$crate::pyo3::Bound<$crate::pyo3::PyAny>,
        ) -> $crate::pyo3::PyResult<std::sync::Arc<$output_type>> {
            use $crate::pyo3::prelude::*;
            use $crate::pyo3::types::PyCapsule;

            let obj = $crate::call_capsule_getter(
                obj.clone(),
                concat!("__", $capsule_name, "__"),
                $crate::CapsuleGetterArg::None,
            )?;
            let capsule = obj.cast::<PyCapsule>().map_err(|_| {
                $crate::errors::py_datafusion_err(concat!(
                    "Invalid ",
                    $capsule_name,
                    ". Does not contain PyCapsule object."
                ))
            })?;
            $crate::validate_pycapsule(&capsule, $capsule_name)?;

            let expected_name = std::ffi::CString::new($capsule_name)
                .expect("capsule name must not contain interior NUL bytes");
            let data: std::ptr::NonNull<$ffi_type> = capsule
                .pointer_checked(Some(expected_name.as_c_str()))?
                .cast();
            let output_obj = unsafe { data.as_ref() };
            let output_obj: std::sync::Arc<$output_type> = output_obj
                .try_into()
                .map_err($crate::errors::py_datafusion_err)?;

            Ok(output_obj)
        }
    };
}

// Re-export pyo3 so the macros expand inside downstream crates without
// requiring an explicit pyo3 dep at the call site.
#[doc(hidden)]
pub use pyo3;

// There is deliberately no `physical_codec_from_pycapsule` here. These macros
// call the getter with no arguments, which is right for the two hooks below but
// wrong for `__datafusion_physical_extension_codec__`, which takes the session
// it is being installed on. Use `ffi_physical_codec_from_pycapsule`, which
// passes the session, and convert with `(&ffi).into()` if you need an
// `Arc<dyn PhysicalExtensionCodec>`.
from_pycapsule!(
    physical_optimizer_rule_from_pycapsule,
    "datafusion_physical_optimizer_rule",
    FFI_PhysicalOptimizerRule,
    dyn PhysicalOptimizerRule + Send + Sync
);

try_from_pycapsule!(
    task_context_from_pycapsule,
    "datafusion_task_context_provider",
    FFI_TaskContextProvider,
    TaskContext
);
