#!/usr/bin/env bash
# mpl-validate-chart: Validate a chart MPL pipeline by simulating the
# dashboard runtime's $__interval injection.
#
# Why this exists:
#   The dashboard runtime auto-declares `param $__interval: Duration;` on
#   every chart query and supplies its value via the request body. The
#   plain `metrics-query` script does NOT — so testing a chart query
#   directly with `metrics-query` fails with `The param $__interval is not
#   defined`. This wrapper does the dance.
#
#   It also rejects inline time ranges (`[1h..]`, `[30d..]`, etc.) up
#   front, with a clear error. Inline ranges deploy fine but render with
#   `AST Error (Time is provided both in the query and as a parameter)` at
#   runtime, because the dashboard always passes start/end via the API.
#
# Usage:
#   mpl-validate-chart <deployment> '<MPL>' [start] [end] [--interval <DUR>]
#
# Defaults:
#   start    = now-1h
#   end      = now
#   interval = 5m
#
# Examples:
#   mpl-validate-chart staging \
#     '`k8s-metrics-staging`:apiserver_request_total
#       | where `service.name` == "apiserver"
#       | align to $__interval using prom::rate
#       | group by code using sum'
#
#   # Override the simulated interval
#   mpl-validate-chart --interval 1h staging \
#     '`k8s-metrics-staging`:process_resident_memory_bytes
#       | align to $__interval using avg'

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
METRICS_QUERY="$SCRIPT_DIR/metrics-query"

INTERVAL="5m"
DEPLOYMENT=""
MPL=""
START="now-1h"
END="now"

POSITIONAL=()
while [[ $# -gt 0 ]]; do
    case "$1" in
        --interval) INTERVAL="$2"; shift 2 ;;
        -h|--help)
            sed -n '2,/^set -euo pipefail/p' "$0" | sed 's/^# \?//' | sed '$d'
            exit 0
            ;;
        --) shift; POSITIONAL+=("$@"); break ;;
        --*) echo "Error: unknown flag '$1'" >&2; exit 1 ;;
        *) POSITIONAL+=("$1"); shift ;;
    esac
done

if [[ ${#POSITIONAL[@]} -lt 2 ]]; then
    echo "Usage: mpl-validate-chart <deployment> '<MPL>' [start] [end] [--interval <DUR>]" >&2
    exit 1
fi

DEPLOYMENT="${POSITIONAL[0]}"
MPL="${POSITIONAL[1]}"
START="${POSITIONAL[2]:-$START}"
END="${POSITIONAL[3]:-$END}"

# --- Reject inline time ranges --------------------------------------------
#
# MPL inline ranges look like `[1h..]`, `[30d..5m]`, `[2025-01-01T..+1h]`,
# `[1747077736..]`, etc. — `..` inside `[]`. MPL doesn't otherwise use `[]`
# at the source level (no list/array literals at the top of the syntax),
# so this regex is safe.

if printf '%s' "$MPL" | grep -qE '\[[^]]*\.\.[^]]*\]'; then
    cat >&2 <<EOF
Error: inline time range detected in MPL (e.g. \`[1h..]\` or \`[30d..]\`).

Dashboard chart queries cannot use inline time ranges — the dashboard
runtime always supplies start/end via the API, and an inline range
collides with that, surfacing as:

    AST Error (Time is provided both in the query and as a parameter)

Remove the inline range. The dashboard time picker (or the dashboard's
\`timeWindowStart\` / \`timeWindowEnd\`) controls the window. Use
\`align to \$__interval using …\` for bucketing.
EOF
    exit 1
fi

# --- Auto-inject `param $__interval: Duration;` if needed ----------------
#
# Only inject and pass `-p __interval=…` when the query actually
# references `$__interval`. Otherwise the server returns the warning
# "These params were provided but not declared: $__interval" — confusing
# noise on a query that has nothing to do with the variable.

USES_INTERVAL=0
WRAPPED="$MPL"
if printf '%s' "$MPL" | grep -qF '$__interval'; then
    USES_INTERVAL=1
    if ! printf '%s' "$MPL" | grep -qE 'param[[:space:]]+\$__interval'; then
        WRAPPED=$(printf 'param $__interval: Duration;\n%s' "$MPL")
    fi
fi

# --- Forward to metrics-query --------------------------------------------

if [[ $USES_INTERVAL -eq 1 ]]; then
    exec "$METRICS_QUERY" -p "__interval=$INTERVAL" "$DEPLOYMENT" "$WRAPPED" "$START" "$END"
else
    exec "$METRICS_QUERY" "$DEPLOYMENT" "$WRAPPED" "$START" "$END"
fi
