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

usage() {
  cat <<'USAGE'
Usage: scripts/configure_shared_go_cache.sh [--root PATH] [--tmpdir PATH] [--tmp-root PATH]

Configures Go module and build caches for GitHub Actions jobs on the shared
self-hosted runner host. Values are written to $GITHUB_ENV when available.

Options:
  --root PATH      Shared Go cache root. Defaults to GO_SHARED_CACHE_ROOT or
                   /var/cache/nexuscrm/github-actions/go.
  --tmpdir PATH    Optional TMPDIR to export for the job.
  --tmp-root PATH  GOTMPDIR to export for the job. Defaults to GOTMPDIR or a
                   run-scoped directory under RUNNER_TEMP or /tmp.
USAGE
}

cache_root="${GO_SHARED_CACHE_ROOT:-/var/cache/nexuscrm/github-actions/go}"
tmpdir="${TMPDIR:-}"
gotmpdir="${GOTMPDIR:-}"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --root)
      [[ $# -ge 2 ]] || { echo "missing value for --root" >&2; exit 2; }
      cache_root="$2"
      shift 2
      ;;
    --tmpdir)
      [[ $# -ge 2 ]] || { echo "missing value for --tmpdir" >&2; exit 2; }
      tmpdir="$2"
      shift 2
      ;;
    --tmp-root|--gotmpdir)
      [[ $# -ge 2 ]] || { echo "missing value for $1" >&2; exit 2; }
      gotmpdir="$2"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "unknown argument: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

command -v go >/dev/null 2>&1 || { echo "missing go in PATH=${PATH}" >&2; exit 1; }

goos="$(go env GOOS)"
goarch="$(go env GOARCH)"
goversion="$(go env GOVERSION)"
run_id="${GITHUB_RUN_ID:-manual}"
run_attempt="${GITHUB_RUN_ATTEMPT:-1}"

if [[ -z "${gotmpdir}" ]]; then
  gotmpdir="${RUNNER_TEMP:-/tmp}/go-build-${run_id}-${run_attempt}"
fi

go_build_cache="${cache_root}/build/${goos}-${goarch}-${goversion}"
go_mod_cache="${cache_root}/mod"
goflags="${GOFLAGS:-}"
if [[ " ${goflags} " != *" -modcacherw "* ]]; then
  if [[ -n "${goflags}" ]]; then
    goflags="-modcacherw ${goflags}"
  else
    goflags="-modcacherw"
  fi
fi

umask 0002
mkdir -p "${cache_root}" "${cache_root}/build" "${go_build_cache}" "${go_mod_cache}" "${gotmpdir}"
if [[ -n "${tmpdir}" ]]; then
  mkdir -p "${tmpdir}"
fi

chmod 2775 "${cache_root}" "${cache_root}/build" "${go_build_cache}" "${go_mod_cache}" 2>/dev/null || true

[[ -w "${go_build_cache}" ]] || { echo "shared Go build cache is not writable: ${go_build_cache}" >&2; exit 1; }
[[ -w "${go_mod_cache}" ]] || { echo "shared Go module cache is not writable: ${go_mod_cache}" >&2; exit 1; }
[[ -w "${gotmpdir}" ]] || { echo "Go temp cache is not writable: ${gotmpdir}" >&2; exit 1; }
if [[ -n "${tmpdir}" ]]; then
  [[ -w "${tmpdir}" ]] || { echo "TMPDIR is not writable: ${tmpdir}" >&2; exit 1; }
fi

write_env() {
  local key="$1"
  local value="$2"
  if [[ -n "${GITHUB_ENV:-}" ]]; then
    printf '%s=%s\n' "${key}" "${value}" >> "${GITHUB_ENV}"
  else
    printf 'export %s=%q\n' "${key}" "${value}"
  fi
}

write_output() {
  local key="$1"
  local value="$2"
  if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
    printf '%s=%s\n' "${key}" "${value}" >> "${GITHUB_OUTPUT}"
  fi
}

write_env "GO_SHARED_CACHE_ROOT" "${cache_root}"
if [[ -n "${tmpdir}" ]]; then
  write_env "TMPDIR" "${tmpdir}"
fi
write_env "GOTMPDIR" "${gotmpdir}"
write_env "GOCACHE" "${go_build_cache}"
write_env "GOMODCACHE" "${go_mod_cache}"
write_env "GOFLAGS" "${goflags}"

write_output "go_shared_cache_root" "${cache_root}"
write_output "go_build_cache" "${go_build_cache}"
write_output "go_mod_cache" "${go_mod_cache}"
write_output "gotmpdir" "${gotmpdir}"

echo "Configured shared Go cache:"
echo "  GO_SHARED_CACHE_ROOT=${cache_root}"
echo "  GOCACHE=${go_build_cache}"
echo "  GOMODCACHE=${go_mod_cache}"
echo "  GOTMPDIR=${gotmpdir}"
echo "  GOFLAGS=${goflags}"
