#!/usr/bin/env bash
set -euo pipefail

usage() {
  cat <<'EOF'
usage: buildbuddy-dev [--dry-run] [--jobs N] <lane> [target-or-bazel-args...]

Runs local developer lanes through the optional BuildBuddy/Bazel backend.
Cargo remains the default path; this script is the readable local facade for
developers who opt in with MEERKAT_BUILDBUDDY=1 or explicit make buildbuddy-*.

Set BUILDBUDDY_DRY_RUN=1 when calling through Make.

Common lanes:
  build, check              Build the generated Rust workspace labels.
  clippy, lint              Run rules_rust clippy with -D warnings.
  test, test-all            Run unit + integration-fast lanes.
  test-unit                 Run unit tests.
  test-int, integration-fast
                            Run integration-fast tests.
  e2e-fast, e2e-system      Run deterministic e2e lanes.
  e2e-live, e2e-smoke       Run live-provider lanes when keys are configured.
  e2e-auth                  Run release-grade auth smoke lane.
  workspace-fast            Run the Cargo-fast-equivalent Bazel suite.
  fmt-static                Run static formatting/source gates.
  minimal                   Run minimal feature builds.
  feature-matrix-lib        Run library feature matrix.
  feature-matrix-surface    Build surface feature variants.
  sdk-suites, wasm-check, wasm-contract, audit
                            Run cargo-equivalent support lanes.
  machine-authority, rmat-audit, seam-inventory
                            Run authority and structural audit lanes.

Examples:
  scripts/buildbuddy-dev build
  scripts/buildbuddy-dev build //meerkat-cli:rkat
  scripts/buildbuddy-dev clippy
  scripts/buildbuddy-dev test
  scripts/buildbuddy-dev --dry-run e2e-fast
EOF
}

workspace_root="$(git rev-parse --show-toplevel)"
cd "${workspace_root}"
source "${workspace_root}/scripts/build-backend-env"

jobs="${BUILDBUDDY_JOBS:-64}"
dry_run=0
case "${BUILDBUDDY_DRY_RUN:-}" in
  1|true|TRUE|yes|YES|on|ON)
    dry_run=1
    ;;
esac

while [[ $# -gt 0 ]]; do
  case "$1" in
    --dry-run)
      dry_run=1
      shift
      ;;
    --jobs)
      if [[ $# -lt 2 ]]; then
        echo "error: --jobs requires a value" >&2
        exit 2
      fi
      jobs="$2"
      shift 2
      ;;
    --jobs=*)
      jobs="${1#--jobs=}"
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    --)
      shift
      break
      ;;
    -*)
      echo "unknown option: $1" >&2
      usage >&2
      exit 2
      ;;
    *)
      break
      ;;
  esac
done

if [[ $# -lt 1 ]]; then
  usage >&2
  exit 2
fi

lane="$1"
shift
extra_args=("$@")

case "${lane}" in
  e2e-live|e2e-smoke)
    meerkat_load_local_secrets_env "${workspace_root}"
    ;;
esac

bb_config="${BUILDBUDDY_BAZEL_CONFIG:-buildbuddy-macos-rbe}"

print_command() {
  printf '+ '
  printf '%q ' "$@"
  printf '\n'
}

run_command() {
  print_command "$@"
  if [[ "${dry_run}" == "1" ]]; then
    return 0
  fi
  "$@"
}

run_bazel() {
  local bazel_command="$1"
  shift
  run_command env \
    BUILDBUDDY_BAZEL_CONFIG="${bb_config}" \
    BUILDBUDDY_BAZEL_COMMAND="${bazel_command}" \
    ./scripts/buildbuddy-bazel-poc "$@" --jobs="${jobs}"
}

run_bazel_with_extra() {
  local bazel_command="$1"
  shift
  if [[ "${#extra_args[@]}" -gt 0 ]]; then
    run_bazel "${bazel_command}" "$@" "${extra_args[@]}"
  else
    run_bazel "${bazel_command}" "$@"
  fi
}

workspace_build_targets() {
  ./scripts/bazel-affected-fast-tests.mjs --all --build
}

e2e_smoke_test_filter() {
  local selection_count=0
  local selection_args=()
  if [[ -n "${TEST:-}" ]]; then
    selection_count=$((selection_count + 1))
    selection_args=(--test "${TEST}")
  fi
  if [[ -n "${SCENARIO:-}" ]]; then
    selection_count=$((selection_count + 1))
    selection_args=(--scenario "${SCENARIO}")
  fi
  if [[ -n "${SUITE:-}" ]]; then
    selection_count=$((selection_count + 1))
    selection_args=(--suite "${SUITE}")
  fi
  if [[ "${selection_count}" -gt 1 ]]; then
    echo "error: provide only one of TEST, SCENARIO, or SUITE" >&2
    exit 2
  fi
  if [[ "${selection_count}" -eq 1 ]]; then
    "${workspace_root}/scripts/e2e-smoke-filter" "${selection_args[@]}"
  fi
}

case "${lane}" in
  build|check)
    if [[ "${#extra_args[@]}" -gt 0 && "${extra_args[0]}" != -* ]]; then
      target="${extra_args[0]}"
      extra_args=("${extra_args[@]:1}")
    else
      target="$(workspace_build_targets)"
    fi
    run_bazel_with_extra build "${target}"
    ;;
  clippy|lint)
    run_bazel_with_extra workspace-build-clippy-rbe --color=no --curses=no
    ;;
  test|test-all)
    run_bazel_with_extra workspace-unit-rbe
    run_bazel_with_extra workspace-integration-fast-rbe
    ;;
  test-unit|unit)
    run_bazel_with_extra workspace-unit-rbe
    ;;
  test-int|integration-fast|int)
    run_bazel_with_extra workspace-integration-fast-rbe
    ;;
  e2e-fast)
    run_bazel_with_extra e2e-fast-rbe
    ;;
  e2e-system)
    run_bazel_with_extra e2e-system-rbe
    ;;
  e2e-live)
    run_bazel_with_extra e2e-live-rbe
    ;;
  e2e-smoke)
    e2e_smoke_test_filter >/dev/null
    run_bazel_with_extra e2e-smoke-rbe
    ;;
  e2e-auth)
    run_bazel_with_extra e2e-auth-rbe
    ;;
  workspace-fast|fast)
    run_bazel_with_extra workspace-fast-rbe
    ;;
  fmt-static)
    run_bazel_with_extra fmt-static-rbe
    ;;
  minimal|minimal-feature-builds)
    run_bazel_with_extra minimal-feature-builds-rbe
    ;;
  feature-matrix-lib)
    run_bazel_with_extra feature-matrix-lib-rbe
    ;;
  feature-matrix-surface)
    run_bazel_with_extra feature-matrix-surface-rbe
    ;;
  sdk-suites)
    run_bazel_with_extra sdk-suites-rbe
    ;;
  wasm-check)
    run_bazel_with_extra wasm-check-rbe
    ;;
  wasm-contract)
    run_bazel_with_extra wasm-contract-rbe
    ;;
  audit|security-audit)
    run_bazel_with_extra security-audit-rbe
    ;;
  machine-authority)
    run_bazel_with_extra machine-authority-rbe
    ;;
  rmat-audit)
    run_bazel_with_extra rmat-audit-rbe
    ;;
  seam-inventory)
    run_bazel_with_extra seam-inventory-rbe
    ;;
  *)
    echo "unknown BuildBuddy developer lane: ${lane}" >&2
    usage >&2
    exit 2
    ;;
esac
