#!/usr/bin/env bash

set -e

# Directory where the script is located
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BIN_DIR="$SCRIPT_DIR/.bin"
DETEKT_VERSION=$(grep -A1 'detekt = ' "$SCRIPT_DIR/../gradle/libs.versions.toml" | head -1 | cut -d'"' -f2)
DETEKT_VERSION_STR="$(echo "$DETEKT_VERSION" | tr '.' '_')"
DETEKT_JAR="$BIN_DIR/detekt_$DETEKT_VERSION_STR.jar"
CONFIG_FILE="$SCRIPT_DIR/../config/detekt/detekt.yml"

# Create bin directory if it doesn't exist
mkdir -p "$BIN_DIR"

# Download detekt if not present
if [ ! -f "$DETEKT_JAR" ]; then
  if [ -n "${VERBOSE:-}" ]; then
    echo "Downloading detekt version $DETEKT_VERSION..." 1>&2
  fi
  tmp_file=$(mktemp)
  trap 'rm -f "$tmp_file"' EXIT
  curl -L --progress-bar "https://github.com/detekt/detekt/releases/download/v$DETEKT_VERSION/detekt-cli-$DETEKT_VERSION-all.jar" -o "$tmp_file"
  mv "$tmp_file" "$DETEKT_JAR"
fi

# Function to find the closest baseline and config files by traversing up the directory tree
find_closest_baseline() {
  local dir="$1"
  local baseline=""
  local git_root="$(git rev-parse --show-toplevel)"
  while [[ "$dir" != "$git_root" ]]; do
    if [[ -z "$baseline" && -f "$dir/config/detekt-baseline.xml" ]]; then
      echo "$dir/config/detekt-baseline.xml"
      return 0
    fi
    dir="$(dirname "$dir")"
  done
  echo ""
}

# Group files by their closest baseline.xml and config
# Use temporary files to simulate associative arrays for bash 3.2 compatibility
tmp_dir=$(mktemp -d)
trap 'rm -rf "$tmp_dir"' EXIT
files_no_baseline=()
args=()

for file in "$@"; do
  if [[ ! -f "$file" ]]; then
    args+=("$file")
    continue
  fi

  dir="$(cd "$(dirname "$file")" && pwd)"
  baseline="$(find_closest_baseline "$dir")"

  if [[ -n "$baseline" ]]; then
    # Create a safe filename for the baseline path
    baseline_key=$(echo "$baseline" | sed 's/[^a-zA-Z0-9]/_/g')
    baseline_file="$tmp_dir/baseline_$baseline_key"

    # Store the actual baseline path
    if [[ ! -f "$baseline_file.path" ]]; then
      echo "$baseline" >"$baseline_file.path"
    fi

    # Append file to the list for this baseline
    echo "$file" >>"$baseline_file.files"
  else
    files_no_baseline+=("$file")
  fi
done

# Process each group with its corresponding baseline and config
exit_code=0
for baseline_file in "$tmp_dir"/baseline_*.files; do
  if [[ -f "$baseline_file" ]]; then
    baseline_path=$(<"${baseline_file%.files}.path")
    files_list=$(tr '\n' ',' <"$baseline_file")
    # Remove trailing comma if present
    files_list=${files_list%,}
    if [ -n "${VERBOSE:-}" ]; then
      echo "Running detekt with baseline: $baseline_path and files: $files_list" >&2
    fi
    if ! java -jar "$DETEKT_JAR" --baseline "$baseline_path" --config "$CONFIG_FILE" "${args[@]}" --input "$files_list" >&2; then
      exit_code=1
    fi
  fi
done

# Process files without a baseline using default config
if [[ ${#files_no_baseline[@]} -gt 0 ]]; then
  if [ -n "${VERBOSE:-}" ]; then
    echo "Running detekt without baseline for remaining files" >&2
  fi
  files_no_baseline_str=$(printf "%s," "${files_no_baseline[@]}")
  files_no_baseline_str=${files_no_baseline_str%,}
  if ! java -jar "$DETEKT_JAR" --config "$CONFIG_FILE" "${args[@]}" --input "$files_no_baseline_str" >&2; then
    exit_code=1
  fi
fi

# If there are no files, print help
has_baseline_files=false
for f in "$tmp_dir"/baseline_*.files; do
  if [[ -f "$f" ]]; then
    has_baseline_files=true
    break
  fi
done

if [[ ${#files_no_baseline[@]} -eq 0 && "$has_baseline_files" = false ]]; then
  exec java -jar "$DETEKT_JAR" --config "$CONFIG_FILE" "${args[@]}" >&2
fi

exit $exit_code
