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

# Script Name: murder
# Description: Gracefully terminate processes with escalating signals
# Source: https://evanhahn.com/scripts-i-wrote-that-i-use-all-the-time/
# Credit: Evan Hahn - https://codeberg.org/EvanHahn/dotfiles
# Usage: murder 1234           # kill PID
#        murder :8080          # kill process on port 8080
#        murder firefox        # kill process by name
#        murder                # interactive fzf picker (integrated with your k alias!)

# Signal escalation: [signal, wait_seconds]
# SIGTERM (15) -> SIGINT (2) -> SIGHUP (1) -> SIGKILL (9)
SIGNALS=("15 3" "2 3" "1 4" "9 0")

murder_pid() {
  local pid=$1

  if ! ps -p "$pid" > /dev/null 2>&1; then
    echo "Process $pid not found" >&2
    return 1
  fi

  local process_name=$(ps -p "$pid" -o comm= 2>/dev/null || echo "unknown")
  echo "Terminating $process_name (PID: $pid)..."

  for sig_wait in "${SIGNALS[@]}"; do
    read -r sig wait <<< "$sig_wait"

    if ! ps -p "$pid" > /dev/null 2>&1; then
      echo "✓ Process terminated successfully"
      return 0
    fi

    case $sig in
      15) echo "  → Sending SIGTERM (polite shutdown)..." ;;
      2)  echo "  → Sending SIGINT (interrupt)..." ;;
      1)  echo "  → Sending SIGHUP (hangup)..." ;;
      9)  echo "  → Sending SIGKILL (force kill)..." ;;
    esac

    kill -"$sig" "$pid" 2>/dev/null || true

    if [[ $wait -gt 0 ]]; then
      sleep "$wait"
    fi
  done

  if ps -p "$pid" > /dev/null 2>&1; then
    echo "✗ Failed to terminate process" >&2
    return 1
  fi

  echo "✓ Process terminated"
}

# If no arguments, use fzf to select process (like your k alias!)
if [[ $# -eq 0 ]]; then
  if ! command -v fzf &>/dev/null; then
    echo "Error: fzf not found. Install fzf or provide PID/name/port as argument." >&2
    exit 1
  fi

  selected=$(ps aux | fzf --header="Select process to terminate (graceful escalation)" \
    --header-lines=1 \
    --preview='echo "Will attempt: SIGTERM → SIGINT → SIGHUP → SIGKILL"')

  if [[ -n "$selected" ]]; then
    pid=$(echo "$selected" | awk '{print $2}')
    murder_pid "$pid"
  fi
  exit 0
fi

# Parse argument: PID, :port, or process name
arg="$1"

if [[ "$arg" =~ ^[0-9]+$ ]]; then
  # Argument is a PID
  murder_pid "$arg"
elif [[ "$arg" =~ ^:[0-9]+$ ]]; then
  # Argument is a port (e.g., :8080)
  port="${arg:1}"
  pid=$(lsof -ti ":$port" 2>/dev/null || true)

  if [[ -z "$pid" ]]; then
    echo "No process found listening on port $port" >&2
    exit 1
  fi

  echo "Found process on port $port:"
  ps -p "$pid" -o pid,comm,args | tail -1
  murder_pid "$pid"
else
  # Argument is a process name
  pids=$(pgrep -f "$arg" || true)

  if [[ -z "$pids" ]]; then
    echo "No processes found matching: $arg" >&2
    exit 1
  fi

  # If multiple processes, show list and let user choose
  count=$(echo "$pids" | wc -l)
  if [[ $count -gt 1 ]]; then
    echo "Multiple processes found matching '$arg':"
    ps -p $pids -o pid,comm,args

    if command -v fzf &>/dev/null; then
      selected=$(ps -p $pids | fzf --header-lines=1)
      if [[ -n "$selected" ]]; then
        pid=$(echo "$selected" | awk '{print $1}')
        murder_pid "$pid"
      fi
    else
      echo -n "Enter PID to terminate: "
      read pid
      murder_pid "$pid"
    fi
  else
    murder_pid "$pids"
  fi
fi
