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

if [[ "$#" -eq 0 ]]; then
  echo "No cache modes specified; skipping."
  exit 0
fi

want_bazel_cache=0
for mode in "$@"; do
  if [[ "$mode" == "bazel" ]]; then
    want_bazel_cache=1
    break
  fi
done

portable_mkdir() {
  hash -r >/dev/null 2>&1 || true
  command -p mkdir "$@"
}

optional_timeout() {
  local duration="$1"
  shift
  if command -v timeout >/dev/null 2>&1; then
    timeout "$duration" "$@"
  else
    "$@"
  fi
}

append_bazel_storage_cache() {
  local bazelrc_path="$1"
  local cache_root="${BURROW_BAZEL_STORAGE_CACHE:-}"
  if [[ -z "$cache_root" && -n "${NSC_CACHE_PATH:-}" ]]; then
    cache_root="${NSC_CACHE_PATH}/bazel"
  fi
  if [[ -z "$cache_root" ]]; then
    return 0
  fi

  portable_mkdir -p "${cache_root}/disk" "${cache_root}/repository"
  {
    echo "build --disk_cache=${cache_root}/disk"
    echo "build --repository_cache=${cache_root}/repository"
  } >> "$bazelrc_path"
  echo "Namespace Bazel storage cache configured: ${cache_root}"
}

configure_bazel_remote_cache() {
  if [[ "$want_bazel_cache" != "1" ]]; then
    return 0
  fi

  local bazelrc_path
  bazelrc_path="${NSC_BAZELRC_PATH:-${TMPDIR:-/tmp}/burrow-nsc-cache.bazelrc}"
  portable_mkdir -p "$(dirname "$bazelrc_path")"

  if [[ "$(uname -s 2>/dev/null || true)" == "Darwin" ]]; then
    append_bazel_storage_cache "$bazelrc_path"
    export BURROW_BAZEL_NSCCACHE_ACTIVE=0
    export BURROW_BAZEL_NSCCACHE_BAZELRC="$bazelrc_path"
    echo "::warning ::Namespace Bazel remote cache probe skipped on macOS; using local Bazel repository/disk cache."
    if [[ -n "${GITHUB_ENV:-}" ]]; then
      echo "BURROW_BAZEL_NSCCACHE_ACTIVE=0" >> "$GITHUB_ENV"
      echo "BURROW_BAZEL_NSCCACHE_BAZELRC=$bazelrc_path" >> "$GITHUB_ENV"
      echo "NSC_BAZELRC_PATH=$bazelrc_path" >> "$GITHUB_ENV"
    fi
    return 0
  fi

  export BURROW_BAZEL_NSCCACHE_ACTIVE=0
  if ! command -v nsc >/dev/null 2>&1; then
    if bash Scripts/ci/ensure-nsc.sh; then
      nsc_bin_dir="${RUNNER_TEMP:-${TMPDIR:-/tmp}}/nsc-bin"
      if [[ -x "${nsc_bin_dir}/nsc" ]]; then
        export PATH="${nsc_bin_dir}:$PATH"
      fi
    else
      echo "::warning ::nsc not found; using local Bazel disk cache only."
      if [[ -n "${GITHUB_ENV:-}" ]]; then
        echo "BURROW_BAZEL_NSCCACHE_ACTIVE=0" >> "$GITHUB_ENV"
      fi
      return 0
    fi
  fi

  local probe_timeout="${BURROW_NSC_CACHE_PROBE_TIMEOUT:-30s}"
  if optional_timeout "$probe_timeout" nsc auth check-login >/dev/null 2>&1 &&
    optional_timeout "$probe_timeout" nsc cache bazel setup --bazelrc "$bazelrc_path" >/dev/null 2>&1; then
    append_bazel_storage_cache "$bazelrc_path"
    export BURROW_BAZEL_NSCCACHE_BAZELRC="$bazelrc_path"
    export BURROW_BAZEL_NSCCACHE_ACTIVE=1
    echo "Namespace Bazel cache configured: $bazelrc_path"
    if [[ -n "${GITHUB_ENV:-}" ]]; then
      {
        echo "BURROW_BAZEL_NSCCACHE_ACTIVE=1"
        echo "BURROW_BAZEL_NSCCACHE_BAZELRC=$bazelrc_path"
        echo "NSC_BAZELRC_PATH=$bazelrc_path"
      } >> "$GITHUB_ENV"
    fi
  else
    append_bazel_storage_cache "$bazelrc_path"
    echo "::warning ::Namespace Bazel remote cache unavailable; using local Bazel repository/disk cache."
    if [[ -n "${GITHUB_ENV:-}" ]]; then
      echo "BURROW_BAZEL_NSCCACHE_ACTIVE=0" >> "$GITHUB_ENV"
      echo "BURROW_BAZEL_NSCCACHE_BAZELRC=$bazelrc_path" >> "$GITHUB_ENV"
      echo "NSC_BAZELRC_PATH=$bazelrc_path" >> "$GITHUB_ENV"
    fi
  fi
}

cache_root="${NSC_CACHE_PATH:-}"
if [[ -z "$cache_root" ]]; then
  ensure_dir() {
    local dir="$1"
    if portable_mkdir -p "$dir" 2>/dev/null; then
      return 0
    fi
    if [[ "$(id -u)" != "0" ]] && command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then
      sudo mkdir -p "$dir" >/dev/null 2>&1 || return 1
      return 0
    fi
    return 1
  }

  if [[ "$(uname -s 2>/dev/null || true)" == "Linux" ]]; then
    tmp_root="${RUNNER_TEMP:-${TMPDIR:-/tmp}}/burrow-nscloud-cache"
    for candidate in "/cache/nscloud" "$tmp_root" "$PWD/.nscloud-cache"; do
      if ensure_dir "$candidate"; then
        cache_root="$candidate"
        break
      fi
    done
  else
    tmp_root="${RUNNER_TEMP:-${TMPDIR:-/tmp}}/burrow-nscloud-cache"
    for candidate in "$tmp_root" "$PWD/.nscloud-cache"; do
      if ensure_dir "$candidate"; then
        cache_root="$candidate"
        break
      fi
    done
  fi
fi

if [[ -z "$cache_root" ]]; then
  echo "NSCloud cache volume not configured (NSC_CACHE_PATH missing); skipping."
  configure_bazel_remote_cache
  exit 0
fi

export NSC_CACHE_PATH="$cache_root"
if [[ -n "${GITHUB_ENV:-}" ]]; then
  echo "NSC_CACHE_PATH=$cache_root" >> "$GITHUB_ENV"
fi

mode_args=()
for mode in "$@"; do
  [[ -z "$mode" ]] && continue
  if [[ "$mode" == "bazel" ]]; then
    continue
  fi
  if [[ "$mode" == "nix" && "${BURROW_NSC_DIRECT_NIX_VOLUME:-0}" == "1" ]]; then
    echo "Namespace Nix cache volume is mounted directly at /nix; skipping spacectl nix mount."
    continue
  fi
  if [[ "$mode" == "nix" && "$(uname -s)" == "Darwin" ]]; then
    echo "Skipping late Nix cache mount on macOS; using existing Nix profile and Bazel cache."
    continue
  fi
  mode_args+=("--mode=${mode}")
done

if [[ "${#mode_args[@]}" -eq 0 ]]; then
  echo "No filesystem cache modes require mounting; skipping spacectl cache mount."
  configure_bazel_remote_cache
  exit 0
fi

spacectl_bin_dir="${RUNNER_TEMP:-${TMPDIR:-/tmp}}/spacectl-bin"
if ! command -v spacectl >/dev/null 2>&1; then
  if ! bash Scripts/ci/ensure-spacectl.sh; then
    echo "::warning ::Unable to install spacectl; skipping filesystem cache mount."
    configure_bazel_remote_cache
    exit 0
  fi
  if [[ -x "${spacectl_bin_dir}/spacectl" ]]; then
    export PATH="${spacectl_bin_dir}:$PATH"
  fi
fi

portable_mkdir -p "$cache_root" 2>/dev/null || true

args=(-o json cache mount "--dry_run=false" "--cache_root=${cache_root}" "${mode_args[@]}")
echo "Mounting NSCloud cache: spacectl ${args[*]//${cache_root}/<cache_root>}"

spacectl_bin="$(command -v spacectl)"
run_mount=("$spacectl_bin" "${args[@]}")
if [[ "$(id -u)" != "0" ]]; then
  if ! command -v sudo >/dev/null 2>&1 || ! sudo -n true >/dev/null 2>&1; then
    echo "::warning ::spacectl cache mount requires passwordless sudo; skipping filesystem cache."
    configure_bazel_remote_cache
    exit 0
  fi
  run_mount=(sudo -n env "PATH=$PATH" "$spacectl_bin" "${args[@]}")
fi

tmp_err="$(mktemp "${TMPDIR:-/tmp}/spacectl.XXXXXX")"
cleanup() {
  rm -f "$tmp_err"
}
trap cleanup EXIT

json=""
if ! json="$("${run_mount[@]}" 2>"$tmp_err")"; then
  echo "::warning ::spacectl cache mount failed; skipping filesystem cache."
  if [[ -n "$json" ]]; then
    printf '%s\n' "$json" || true
  fi
  if [[ -s "$tmp_err" ]]; then
    sed -n '1,200p' "$tmp_err" || true
  fi
  configure_bazel_remote_cache
  exit 0
fi

if command -v python3 >/dev/null 2>&1; then
  NSC_MOUNT_JSON="$json" python3 - <<'PY'
import json
import os
import sys

raw = os.environ.get("NSC_MOUNT_JSON", "").strip()
if not raw:
    sys.exit(0)

try:
    payload = json.loads(raw)
except Exception as exc:
    print(f"::warning ::Unable to parse spacectl JSON output; skipping cache env export: {exc}")
    sys.exit(0)

if payload.get("error"):
    print(f"::warning ::spacectl cache mount skipped: {payload.get('message') or 'error=true'}")
    sys.exit(0)

add_envs = (payload.get("output") or {}).get("add_envs") or {}
gh_env = os.environ.get("GITHUB_ENV")
if gh_env and isinstance(add_envs, dict):
    with open(gh_env, "a", encoding="utf-8") as f:
        for key, value in add_envs.items():
            if key and value is not None:
                f.write(f"{key}={value}\n")
PY
fi

configure_bazel_remote_cache
