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

# Script Name: tunnel
# Description: SSH tunnel manager with saved configurations
# Usage: tunnel list                           # List saved tunnels
#        tunnel add name user@host:port ...    # Add new tunnel config
#        tunnel start name                     # Start a saved tunnel
#        tunnel stop name                      # Stop a running tunnel
#        tunnel status                         # Show active tunnels

VERSION="1.0.0"
TUNNEL_DIR="$HOME/.tunnels"
TUNNEL_CONF="$TUNNEL_DIR/tunnels.conf"
PID_DIR="$TUNNEL_DIR/pids"

# Colors
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly CYAN='\033[0;36m'
readonly MAGENTA='\033[0;35m'
readonly BOLD='\033[1m'
readonly NC='\033[0m'

# Initialize tunnel directory
init_tunnel() {
  if [[ ! -d "$TUNNEL_DIR" ]]; then
    mkdir -p "$TUNNEL_DIR" "$PID_DIR"
    touch "$TUNNEL_CONF"
  fi
}

show_help() {
  echo -e "${BOLD}tunnel${NC} - SSH Tunnel Manager v${VERSION}"
  echo
  echo -e "${BOLD}USAGE:${NC}"
  echo "  tunnel <COMMAND> [OPTIONS]"
  echo
  echo -e "${BOLD}COMMANDS:${NC}"
  echo -e "  ${CYAN}list${NC}                List all saved tunnels"
  echo -e "  ${CYAN}add NAME SPEC${NC}       Add new tunnel configuration"
  echo -e "  ${CYAN}start NAME${NC}          Start a saved tunnel"
  echo -e "  ${CYAN}stop NAME${NC}           Stop a running tunnel"
  echo -e "  ${CYAN}restart NAME${NC}        Restart a tunnel"
  echo -e "  ${CYAN}status${NC}              Show active tunnels"
  echo -e "  ${CYAN}delete NAME${NC}         Delete saved tunnel"
  echo -e "  ${CYAN}edit NAME${NC}           Edit tunnel configuration"
  echo
  echo -e "${BOLD}TUNNEL TYPES:${NC}"
  echo -e "  ${YELLOW}Local forward:${NC}   -L local_port:remote_host:remote_port"
  echo -e "  ${YELLOW}Remote forward:${NC}  -R remote_port:local_host:local_port"
  echo -e "  ${YELLOW}Dynamic (SOCKS):${NC} -D local_port"
  echo
  echo -e "${BOLD}EXAMPLES:${NC}"
  echo "  # Forward local port 3000 to remote port 80"
  echo "  tunnel add web user@server.com -L 3000:localhost:80"
  echo
  echo "  # Expose local port 8080 on remote port 9000"
  echo "  tunnel add reverse user@server.com -R 9000:localhost:8080"
  echo
  echo "  # SOCKS proxy on local port 1080"
  echo "  tunnel add socks user@server.com -D 1080"
  echo
  echo "  # Multiple forwards"
  echo "  tunnel add multi user@server.com -L 3000:localhost:80 -L 5432:localhost:5432"
  echo
  echo "  # Start/stop tunnels"
  echo "  tunnel start web"
  echo "  tunnel stop web"
  echo "  tunnel status"
}

# Add tunnel configuration
add_tunnel() {
  local name="$1"
  shift
  local ssh_target="$1"
  shift
  local ssh_args="$*"

  if grep -q "^$name|" "$TUNNEL_CONF" 2>/dev/null; then
    echo -e "${RED}Error:${NC} Tunnel '$name' already exists"
    echo "Use: tunnel delete $name (then re-add)"
    return 1
  fi

  echo "$name|$ssh_target|$ssh_args" >> "$TUNNEL_CONF"
  echo -e "${GREEN}✓${NC} Added tunnel: ${BOLD}$name${NC}"
  echo -e "  Target: $ssh_target"
  echo -e "  Args: $ssh_args"
}

# List tunnels
list_tunnels() {
  if [[ ! -f "$TUNNEL_CONF" ]] || [[ ! -s "$TUNNEL_CONF" ]]; then
    echo -e "${YELLOW}No tunnels configured${NC}"
    echo "Add one with: tunnel add <name> <user@host> <args>"
    return 0
  fi

  echo -e "${BOLD}${CYAN}Saved Tunnels:${NC}"
  echo

  while IFS='|' read -r name target args; do
    # Check if running
    pid_file="$PID_DIR/$name.pid"
    if [[ -f "$pid_file" ]]; then
      pid=$(cat "$pid_file")
      if ps -p "$pid" &>/dev/null; then
        status="${GREEN}●${NC} running"
      else
        status="${RED}●${NC} dead"
        rm -f "$pid_file"
      fi
    else
      status="${YELLOW}○${NC} stopped"
    fi

    echo -e "  [$status] ${BOLD}$name${NC}"
    echo -e "      Target: $target"
    echo -e "      Args:   $args"
    echo
  done < "$TUNNEL_CONF"
}

# Get tunnel config
get_tunnel() {
  local name="$1"

  if [[ ! -f "$TUNNEL_CONF" ]]; then
    echo -e "${RED}Error:${NC} No tunnels configured" >&2
    return 1
  fi

  local line=$(grep "^$name|" "$TUNNEL_CONF")
  if [[ -z "$line" ]]; then
    echo -e "${RED}Error:${NC} Tunnel '$name' not found" >&2
    return 1
  fi

  echo "$line"
}

# Start tunnel
start_tunnel() {
  local name="$1"

  local config=$(get_tunnel "$name")
  IFS='|' read -r _ target args <<< "$config"

  pid_file="$PID_DIR/$name.pid"

  # Check if already running
  if [[ -f "$pid_file" ]]; then
    pid=$(cat "$pid_file")
    if ps -p "$pid" &>/dev/null; then
      echo -e "${YELLOW}⚠${NC} Tunnel '$name' is already running (PID: $pid)"
      return 0
    else
      rm -f "$pid_file"
    fi
  fi

  echo -e "${CYAN}[*]${NC} Starting tunnel: ${BOLD}$name${NC}"
  echo -e "  Target: $target"
  echo -e "  Args: $args"

  # Start SSH tunnel in background
  ssh -f -N $args "$target" &
  local pid=$!

  echo "$pid" > "$pid_file"
  echo -e "${GREEN}✓${NC} Tunnel started (PID: $pid)"
}

# Stop tunnel
stop_tunnel() {
  local name="$1"

  pid_file="$PID_DIR/$name.pid"

  if [[ ! -f "$pid_file" ]]; then
    echo -e "${YELLOW}⚠${NC} Tunnel '$name' is not running"
    return 0
  fi

  pid=$(cat "$pid_file")

  if ! ps -p "$pid" &>/dev/null; then
    echo -e "${YELLOW}⚠${NC} Tunnel process not found (stale PID file)"
    rm -f "$pid_file"
    return 0
  fi

  echo -e "${CYAN}[*]${NC} Stopping tunnel: ${BOLD}$name${NC} (PID: $pid)"
  kill "$pid" 2>/dev/null || true

  # Wait a moment and verify
  sleep 1
  if ps -p "$pid" &>/dev/null; then
    echo -e "${YELLOW}⚠${NC} Process didn't stop gracefully, using SIGKILL"
    kill -9 "$pid" 2>/dev/null || true
  fi

  rm -f "$pid_file"
  echo -e "${GREEN}✓${NC} Tunnel stopped"
}

# Restart tunnel
restart_tunnel() {
  local name="$1"

  echo -e "${CYAN}[*]${NC} Restarting tunnel: ${BOLD}$name${NC}"
  stop_tunnel "$name"
  sleep 1
  start_tunnel "$name"
}

# Show status of all tunnels
show_status() {
  echo -e "${BOLD}${CYAN}Active SSH Tunnels:${NC}"
  echo

  local found_any=false

  if [[ -f "$TUNNEL_CONF" ]]; then
    while IFS='|' read -r name target args; do
      pid_file="$PID_DIR/$name.pid"
      if [[ -f "$pid_file" ]]; then
        pid=$(cat "$pid_file")
        if ps -p "$pid" &>/dev/null; then
          found_any=true
          echo -e "  ${GREEN}●${NC} ${BOLD}$name${NC} (PID: $pid)"
          echo -e "      $target $args"
          echo
        fi
      fi
    done < "$TUNNEL_CONF"
  fi

  if [[ "$found_any" == "false" ]]; then
    echo -e "  ${YELLOW}No active tunnels${NC}"
  fi
}

# Delete tunnel
delete_tunnel() {
  local name="$1"

  if ! grep -q "^$name|" "$TUNNEL_CONF" 2>/dev/null; then
    echo -e "${RED}Error:${NC} Tunnel '$name' not found"
    return 1
  fi

  # Stop if running
  pid_file="$PID_DIR/$name.pid"
  if [[ -f "$pid_file" ]]; then
    echo -e "${YELLOW}⚠${NC} Stopping running tunnel first..."
    stop_tunnel "$name"
  fi

  # Remove from config
  sed -i "/^$name|/d" "$TUNNEL_CONF"
  echo -e "${GREEN}✓${NC} Deleted tunnel: ${BOLD}$name${NC}"
}

# Edit tunnel
edit_tunnel() {
  local name="$1"

  if ! grep -q "^$name|" "$TUNNEL_CONF" 2>/dev/null; then
    echo -e "${RED}Error:${NC} Tunnel '$name' not found"
    return 1
  fi

  "${EDITOR:-vim}" "$TUNNEL_CONF"
  echo -e "${GREEN}✓${NC} Configuration updated"
}

# Initialize
init_tunnel

# Parse command
if [[ $# -eq 0 ]] || [[ "$1" =~ ^(-h|--help|help)$ ]]; then
  show_help
  exit 0
fi

command="$1"
shift

case "$command" in
  list|ls)
    list_tunnels
    ;;
  add|new)
    if [[ $# -lt 2 ]]; then
      echo -e "${RED}Error:${NC} Usage: tunnel add <name> <user@host> <args>"
      exit 1
    fi
    add_tunnel "$@"
    ;;
  start|up)
    if [[ $# -lt 1 ]]; then
      echo -e "${RED}Error:${NC} Usage: tunnel start <name>"
      exit 1
    fi
    start_tunnel "$1"
    ;;
  stop|down)
    if [[ $# -lt 1 ]]; then
      echo -e "${RED}Error:${NC} Usage: tunnel stop <name>"
      exit 1
    fi
    stop_tunnel "$1"
    ;;
  restart)
    if [[ $# -lt 1 ]]; then
      echo -e "${RED}Error:${NC} Usage: tunnel restart <name>"
      exit 1
    fi
    restart_tunnel "$1"
    ;;
  status|ps)
    show_status
    ;;
  delete|del|rm)
    if [[ $# -lt 1 ]]; then
      echo -e "${RED}Error:${NC} Usage: tunnel delete <name>"
      exit 1
    fi
    delete_tunnel "$1"
    ;;
  edit)
    if [[ $# -lt 1 ]]; then
      echo -e "${RED}Error:${NC} Usage: tunnel edit <name>"
      exit 1
    fi
    edit_tunnel "$1"
    ;;
  *)
    echo -e "${RED}Error:${NC} Unknown command: $command"
    echo "Run 'tunnel --help' for usage"
    exit 1
    ;;
esac
