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

# ---------- config ----------
# Paths (relative to repo root) to exclude.
# Each entry excludes that directory AND all its subdirectories.
EXCLUDED_PATH_PREFIXES=(
  "testing"
  "validator/client/testutil"
  "beacon-chain/p2p/testing"
  "beacon-chain/rpc/eth/config"
  "beacon-chain/rpc/prysm/v1alpha1/debug"
  "tools"
  "runtime"
  "monitoring"
  "io"
  "cmd"
  ".well-known"
  "changelog"
  "hack"
  "specrefs"
  "third_party"
  "bazel-out"
  "bazel-bin"
  "bazel-prysm"
  "bazel-testlogs"
  "build"
  ".git"
  ".github"
  ".jj"
  ".idea"
  ".vscode"
)

# The logrus import path
LOGRUS_IMPORT="github.com/sirupsen/logrus"
# ----------------------------

# Require ripgrep
if ! command -v rg >/dev/null 2>&1; then
  echo "Error: ripgrep (rg) is required but not installed." >&2
  exit 1
fi

# Find project root (git repo root if available, else current dir)
ROOT_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
cd "$ROOT_DIR"

# Helper: return 0 if path starts with any excluded prefix
is_excluded() {
  local rel="$1"
  rel="${rel#./}"   # strip leading "./" if present

  for ex in "${EXCLUDED_PATH_PREFIXES[@]}"; do
    if [[ "$rel" == "$ex" || "$rel" == "$ex"/* ]]; then
      return 0
    fi
  done
  return 1
}

# Build rg command:
# - respects .gitignore automatically
# - searches only *.go, excluding *_test.go
# - excludes EXCLUDED_PATH_PREFIXES via negative globs so rg doesn't even enter them
rg_args=(
  rg -F "$LOGRUS_IMPORT"
  --glob '*.go'
  --glob '!*_test.go'
  -l    # list matching files
  -0    # NUL-delimited output
)

for ex in "${EXCLUDED_PATH_PREFIXES[@]}"; do
  rg_args+=( --glob "!$ex/**" )
done

# 1) Use ripgrep to find all non-test .go files that import logrus.
mapfile -d '' -t FILES < <(
  "${rg_args[@]}" . || true
)

# 2) Collect unique directories containing such files (is_excluded is now redundant but harmless)
declare -A DIRS=()
for f in "${FILES[@]}"; do
  dir="$(dirname "$f")"
  if is_excluded "$dir"; then
    continue
  fi
  DIRS["$dir"]=1
done

# 3) For each directory, (re)generate log.go
for dir in "${!DIRS[@]}"; do
  # Collect Go files in this directory
  shopt -s nullglob
  gofiles=( "$dir"/*.go )
  shopt -u nullglob
  if [[ ${#gofiles[@]} -eq 0 ]]; then
    continue
  fi

  # Prefer non-log.go, non-test files to determine package name
  src_files=()
  for gf in "${gofiles[@]}"; do
    base="$(basename "$gf")"
    if [[ "$base" == "log.go" ]]; then
      continue
    fi
    if [[ "$base" == *_test.go ]]; then
      continue
    fi
    src_files+=( "$gf" )
  done

  # Fallback: if there are no such files, use whatever .go files exist (e.g. only log.go)
  if [[ ${#src_files[@]} -eq 0 ]]; then
    src_files=( "${gofiles[@]}" )
  fi

  pkg_name="$(
    grep -h '^package ' "${src_files[@]}" \
      | head -n 1 \
      | awk '{print $2}'
  )"

  if [[ -z "$pkg_name" ]]; then
    echo "Could not determine package name for $dir, skipping"
    continue
  fi

  # Path relative to project root (no project name)
  rel_path="${dir#./}"

  cat > "$dir/log.go" <<EOF
// Code generated by hack/gen-logs.sh; DO NOT EDIT.
// This file is created and regenerated automatically. Anything added here might get removed.
package $pkg_name

import "github.com/sirupsen/logrus"

// The prefix for logs from this package will be the text after the last slash in the package path.
// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file.
var log = logrus.WithField("package", "$rel_path")
EOF

  echo "Wrote $dir/log.go (package: $pkg_name, path: $rel_path)"
done
