#!/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"
KTLINT_VERSION=$(grep -A1 'ktlint = ' "$SCRIPT_DIR/../gradle/libs.versions.toml" | head -1 | cut -d'"' -f2)
KTLINT_VERSION_STR="$(echo "$KTLINT_VERSION" | tr '.' '_')"
KTLINT_BIN="$BIN_DIR/ktlint_$KTLINT_VERSION_STR"

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

# Download ktlint if not present
if [ ! -f "$KTLINT_BIN" ]; then
  tmp_file=$(mktemp)
  trap 'rm -f "$tmp_file"' EXIT
  if [ -n "${VERBOSE:-}" ]; then
    echo "Downloading ktlint version $KTLINT_VERSION..." >&2
  fi
  curl -L --progress-bar "https://github.com/pinterest/ktlint/releases/download/$KTLINT_VERSION/ktlint" -o "$tmp_file"
  chmod +x "$tmp_file"
  mv "$tmp_file" "$KTLINT_BIN"
fi

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

# Group files by their closest baseline.xml
# 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 arg in "$@"; do
  if [[ ! -f "$arg" ]]; then
    args+=("$arg")
    continue
  fi
  file="$arg"

  dir="$(cd "$(dirname "$arg")" && 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
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")
    if [ -n "${VERBOSE:-}" ]; then
      echo "Running ktlint with baseline: $baseline_path and files: $files_list" >&2
    fi
    if ! $KTLINT_BIN "${args[@]}" --baseline="$baseline_path" $files_list >&2; then
      exit_code=1
    fi
  fi
done

# Run for files without a baseline
if [[ ${#files_no_baseline[@]} -gt 0 ]]; then
  if [ -n "${VERBOSE:-}" ]; then
    echo "Running ktlint without baseline for remaining files ${files_no_baseline[*]}" >&2
  fi
  if ! $KTLINT_BIN "${args[@]}" "${files_no_baseline[@]}" >&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 "$KTLINT_BIN" "${args[@]}" >&2
fi

exit $exit_code
