#!/bin/bash

# Count lines of code per author email in the current git branch
# with options to ignore specific files

# Function to show usage
show_usage() {
  echo "Usage: bash <(curl -s http://your-server.com/count_lines.sh) [--ignore pattern1] [--branch branch_name] ..."
  exit 1
}

# Check if we're in a git repository
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
  echo "Error: Not in a git repository"
  exit 1
fi

# Initialize variables
declare -A email_lines
total_lines=0
ignore_patterns=()
branch=$(git rev-parse --abbrev-ref HEAD) # Default to current branch

# Parse command line arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    --ignore)
      if [[ -n "$2" ]]; then
        ignore_patterns+=("$2")
        shift 2
      else
        echo "Error: --ignore requires a pattern"
        show_usage
      fi
      ;;
    --branch)
      if [[ -n "$2" ]]; then
        branch="$2"
        shift 2
      else
        echo "Error: --branch requires a branch name"
        show_usage
      fi
      ;;
    --help|-h)
      show_usage
      ;;
    *)
      echo "Unknown option: $1"
      show_usage
      ;;
  esac
done

# Find the merge base with main/master to get only commits unique to this branch
main_branch="main"
if ! git show-ref --verify --quiet refs/heads/main; then
  if git show-ref --verify --quiet refs/heads/master; then
    main_branch="master"
  fi
fi

# Get range of commits for the current branch only
# If it's main/master, we use all commits
if [[ "$branch" == "$main_branch" ]]; then
  commit_range=""
  echo "Analyzing all commits in $branch"
else
  merge_base=$(git merge-base $branch $main_branch)
  commit_range="$merge_base..$branch"
  echo "Analyzing commits unique to $branch (from merge base with $main_branch)"
fi

# Build the git ls-files command with ignore patterns
ls_files_cmd="git ls-files"
for pattern in "${ignore_patterns[@]}"; do
  ls_files_cmd+=" ':!$pattern'"
done

# Get the list of files to analyze, excluding ignored patterns
files=$(eval $ls_files_cmd)

echo "Counting lines of code per email..."
echo "-----------------------------------"
if [ ${#ignore_patterns[@]} -gt 0 ]; then
  echo "Ignoring patterns: ${ignore_patterns[*]}"
fi
echo

# Get all author emails in the specified range
if [[ -z "$commit_range" ]]; then
  emails=$(git log --format='%ae' | sort -u)
else
  emails=$(git log --format='%ae' $commit_range | sort -u)
fi

# Loop through each email
for email in $emails; do
  lines=0

  # Process each file individually to apply ignore patterns
  for file in $files; do
    # Count lines authored by this email for this file in the specified range
    if [[ -z "$commit_range" ]]; then
      file_lines=$(git log -p --author="$email" -- "$file" | grep -e "^+" -e "^-" | grep -v "^+++ " | grep -v "^--- " | wc -l)
    else
      file_lines=$(git log -p --author="$email" $commit_range -- "$file" | grep -e "^+" -e "^-" | grep -v "^+++ " | grep -v "^--- " | wc -l)
    fi
    lines=$((lines + file_lines))
  done

  # Store the count for this email
  email_lines["$email"]=$lines

  # Add to total
  total_lines=$((total_lines + lines))
done

# Print results and percentages
echo "EMAIL                               LINES     PERCENTAGE"
echo "-----                               -----     ----------"

# Sort emails by line count (highest first)
for email in $(for e in "${!email_lines[@]}"; do echo "$e ${email_lines[$e]}"; done | sort -rn -k2 | awk '{print $1}'); do
  lines=${email_lines["$email"]}

  # Calculate percentage (avoid division by zero)
  if [ $total_lines -eq 0 ]; then
    percentage=0
  else
    percentage=$(echo "scale=2; 100 * $lines / $total_lines" | bc)
  fi

  # Print with formatting
  printf "%-35s %-10s %s%%\n" "$email" "$lines" "$percentage"
done

echo "-----------------------------------"
echo "TOTAL:                             $total_lines     100%"
