// SPDX-License-Identifier: Apache-2.0

//! Aggregate and window function registrations.

use nodedb_types::columnar::ColumnType;

use crate::functions::arg_types;
use crate::functions::registry::{FunctionCategory, FunctionMeta};

use super::helpers::{m, no_trigger};

pub(super) fn aggregate_functions() -> Vec<FunctionMeta> {
    vec![
        // ── Standard aggregates ──
        m(
            "count",
            FunctionCategory::Aggregate,
            0,
            1,
            no_trigger(),
            Some(ColumnType::Int64),
            arg_types::COUNT_ARGS,
        ),
        m(
            "sum",
            FunctionCategory::Aggregate,
            1,
            1,
            no_trigger(),
            None,
            arg_types::SUM_ARGS,
        ),
        m(
            "avg",
            FunctionCategory::Aggregate,
            1,
            1,
            no_trigger(),
            None,
            arg_types::AVG_ARGS,
        ),
        m(
            "min",
            FunctionCategory::Aggregate,
            1,
            1,
            no_trigger(),
            None,
            arg_types::MIN_ARGS,
        ),
        m(
            "max",
            FunctionCategory::Aggregate,
            1,
            1,
            no_trigger(),
            None,
            arg_types::MAX_ARGS,
        ),
        // ── Standard window ──
        m(
            "row_number",
            FunctionCategory::Window,
            0,
            0,
            no_trigger(),
            Some(ColumnType::Int64),
            arg_types::NO_ARGS,
        ),
        m(
            "rank",
            FunctionCategory::Window,
            0,
            0,
            no_trigger(),
            Some(ColumnType::Int64),
            arg_types::NO_ARGS,
        ),
        m(
            "dense_rank",
            FunctionCategory::Window,
            0,
            0,
            no_trigger(),
            Some(ColumnType::Int64),
            arg_types::NO_ARGS,
        ),
        m(
            "lag",
            FunctionCategory::Window,
            1,
            3,
            no_trigger(),
            None,
            arg_types::LAG_LEAD_ARGS,
        ),
        m(
            "lead",
            FunctionCategory::Window,
            1,
            3,
            no_trigger(),
            None,
            arg_types::LAG_LEAD_ARGS,
        ),
        m(
            "first_value",
            FunctionCategory::Window,
            1,
            1,
            no_trigger(),
            None,
            arg_types::FIRST_LAST_VALUE_ARGS,
        ),
        m(
            "last_value",
            FunctionCategory::Window,
            1,
            1,
            no_trigger(),
            None,
            arg_types::FIRST_LAST_VALUE_ARGS,
        ),
        m(
            "nth_value",
            FunctionCategory::Window,
            2,
            2,
            no_trigger(),
            None,
            arg_types::NTH_VALUE_ARGS,
        ),
        m(
            "ntile",
            FunctionCategory::Window,
            1,
            1,
            no_trigger(),
            Some(ColumnType::Int64),
            arg_types::NTILE_ARGS,
        ),
        m(
            "percent_rank",
            FunctionCategory::Window,
            0,
            0,
            no_trigger(),
            Some(ColumnType::Float64),
            arg_types::NO_ARGS,
        ),
        m(
            "cume_dist",
            FunctionCategory::Window,
            0,
            0,
            no_trigger(),
            Some(ColumnType::Float64),
            arg_types::NO_ARGS,
        ),
        // ── Timeseries aggregates ──
        m(
            "ts_percentile",
            FunctionCategory::Aggregate,
            2,
            2,
            no_trigger(),
            None,
            arg_types::TS_PERCENTILE_ARGS,
        ),
        m(
            "ts_stddev",
            FunctionCategory::Aggregate,
            1,
            1,
            no_trigger(),
            None,
            arg_types::TS_STDDEV_ARGS,
        ),
        m(
            "ts_correlate",
            FunctionCategory::Aggregate,
            2,
            2,
            no_trigger(),
            None,
            arg_types::TS_CORRELATE_ARGS,
        ),
        // ── Timeseries window ──
        m(
            "ts_rate",
            FunctionCategory::Window,
            1,
            1,
            no_trigger(),
            None,
            arg_types::TS_WINDOW_1_ARGS,
        ),
        m(
            "ts_derivative",
            FunctionCategory::Window,
            1,
            1,
            no_trigger(),
            None,
            arg_types::TS_WINDOW_1_ARGS,
        ),
        m(
            "ts_moving_avg",
            FunctionCategory::Window,
            2,
            2,
            no_trigger(),
            None,
            arg_types::TS_MOVING_AVG_ARGS,
        ),
        m(
            "ts_ema",
            FunctionCategory::Window,
            2,
            2,
            no_trigger(),
            None,
            arg_types::TS_EMA_ARGS,
        ),
        m(
            "ts_delta",
            FunctionCategory::Window,
            1,
            1,
            no_trigger(),
            None,
            arg_types::TS_WINDOW_1_ARGS,
        ),
        m(
            "ts_interpolate",
            FunctionCategory::Window,
            1,
            1,
            no_trigger(),
            None,
            arg_types::TS_WINDOW_1_ARGS,
        ),
        m(
            "ts_lag",
            FunctionCategory::Window,
            1,
            3,
            no_trigger(),
            None,
            arg_types::TS_LAG_LEAD_ARGS,
        ),
        m(
            "ts_lead",
            FunctionCategory::Window,
            1,
            3,
            no_trigger(),
            None,
            arg_types::TS_LAG_LEAD_ARGS,
        ),
        m(
            "ts_rank",
            FunctionCategory::Window,
            0,
            0,
            no_trigger(),
            None,
            arg_types::NO_ARGS,
        ),
        // ── Approximate aggregates ──
        m(
            "approx_count_distinct",
            FunctionCategory::Aggregate,
            1,
            1,
            no_trigger(),
            None,
            arg_types::APPROX_COUNT_DISTINCT_ARGS,
        ),
        m(
            "approx_percentile",
            FunctionCategory::Aggregate,
            2,
            2,
            no_trigger(),
            None,
            arg_types::APPROX_PERCENTILE_ARGS,
        ),
        m(
            "approx_topk",
            FunctionCategory::Aggregate,
            2,
            2,
            no_trigger(),
            None,
            arg_types::APPROX_TOPK_ARGS,
        ),
        m(
            "approx_count",
            FunctionCategory::Aggregate,
            1,
            1,
            no_trigger(),
            None,
            arg_types::APPROX_COUNT_ARGS,
        ),
        // ── Grouping set functions ──
        // `GROUPING(col)` returns 1 when `col` is NULL because it was not selected
        // in the current grouping set's row (e.g. a ROLLUP grand-total row),
        // and 0 when `col` carries a real aggregated value.
        // Registered as Scalar so it is NOT treated as a GROUP-BY aggregate by
        // aggregate_walk; it is handled specially in plan_aggregate.
        m(
            "grouping",
            FunctionCategory::Scalar,
            1,
            255,
            no_trigger(),
            Some(ColumnType::Int64),
            arg_types::GROUPING_ARGS,
        ),
    ]
}
