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

# Script Name: myip
# Description: Show external and internal IP addresses with optional features
# Usage: myip           # Show all IPs
#        myip -e        # External IP only
#        myip -i        # Internal IPs only
#        myip -c        # Copy external IP to clipboard
#        myip -j        # JSON output
#        myip -a        # All info (IPs + gateway + DNS)

VERSION="1.0.0"

# 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'

show_help() {
  echo -e "${BOLD}myip${NC} - IP Address Information Tool v${VERSION}"
  echo
  echo -e "${BOLD}USAGE:${NC}"
  echo "  myip [OPTIONS]"
  echo
  echo -e "${BOLD}OPTIONS:${NC}"
  echo -e "  ${CYAN}-e, --external${NC}    Show external IP only"
  echo -e "  ${CYAN}-i, --internal${NC}    Show internal IPs only"
  echo -e "  ${CYAN}-c, --copy${NC}        Copy external IP to clipboard"
  echo -e "  ${CYAN}-j, --json${NC}        Output as JSON"
  echo -e "  ${CYAN}-a, --all${NC}         Show all network info (IPs + gateway + DNS)"
  echo -e "  ${CYAN}-h, --help${NC}        Show this help message"
  echo
  echo -e "${BOLD}EXAMPLES:${NC}"
  echo "  myip              # Show both external and internal IPs"
  echo "  myip -e           # External IP only"
  echo "  myip -c           # Copy external IP to clipboard"
  echo "  myip -j           # JSON format for scripting"
  echo "  myip -a           # Complete network information"
  echo
  echo -e "${BOLD}OUTPUT:${NC}"
  echo "  External IP, Internal IPs, Gateway (with -a), DNS servers (with -a)"
}

# Get external IP with fallback sources
get_external_ip() {
  local ip=""

  # Try multiple sources for reliability
  sources=(
    "https://ifconfig.me"
    "https://api.ipify.org"
    "https://icanhazip.com"
    "https://checkip.amazonaws.com"
  )

  for source in "${sources[@]}"; do
    ip=$(curl -sf --max-time 3 "$source" 2>/dev/null | tr -d '[:space:]')
    if [[ -n "$ip" ]] && [[ "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
      echo "$ip"
      return 0
    fi
  done

  echo "unable to fetch" >&2
  return 1
}

# Get internal IPs
get_internal_ips() {
  if command -v ip &>/dev/null; then
    # Modern Linux
    ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1'
  elif command -v ifconfig &>/dev/null; then
    # macOS / older Linux
    ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'
  else
    echo "No network tools found" >&2
    return 1
  fi
}

# Get internal IPs with interface names
get_internal_ips_detailed() {
  if command -v ip &>/dev/null; then
    ip -4 addr show | awk '
      /^[0-9]+:/ { iface = $2; gsub(/:/, "", iface) }
      /inet / && !/127\.0\.0\.1/ {
        split($2, a, "/")
        print iface ":" a[1]
      }
    '
  elif command -v ifconfig &>/dev/null; then
    ifconfig | awk '
      /^[a-z]/ { iface = $1; gsub(/:/, "", iface) }
      /inet / && !/127\.0\.0\.1/ {
        for (i=1; i<=NF; i++) {
          if ($i == "inet") {
            print iface ":" $(i+1)
            break
          }
        }
      }
    '
  fi
}

# Get default gateway
get_gateway() {
  if command -v ip &>/dev/null; then
    ip route | grep default | awk '{print $3}' | head -1
  elif command -v route &>/dev/null; then
    route -n | grep '^0.0.0.0' | awk '{print $2}' | head -1
  elif command -v netstat &>/dev/null; then
    netstat -rn | grep default | awk '{print $2}' | head -1
  else
    echo "unknown"
  fi
}

# Get DNS servers
get_dns_servers() {
  if [[ -f /etc/resolv.conf ]]; then
    grep nameserver /etc/resolv.conf | awk '{print $2}' | tr '\n' ' '
  else
    echo "unknown"
  fi
}

# JSON output
json_output() {
  local external_ip=$(get_external_ip || echo "unknown")
  local internal_ips=$(get_internal_ips | tr '\n' ',' | sed 's/,$//')
  local gateway=$(get_gateway)
  local dns=$(get_dns_servers)

  cat << EOF
{
  "external_ip": "$external_ip",
  "internal_ips": [$( echo "$internal_ips" | sed 's/,/","/g; s/^/"/; s/$/"/' )],
  "gateway": "$gateway",
  "dns_servers": [$( echo "$dns" | sed 's/ /","/g; s/^/"/; s/$/"/' )]
}
EOF
}

# Colorized output
colorized_output() {
  local show_external=${1:-true}
  local show_internal=${2:-true}
  local show_all=${3:-false}

  if [[ "$show_external" == "true" ]]; then
    echo -e "${BOLD}${CYAN}External IP:${NC}"
    external_ip=$(get_external_ip || echo "${RED}Unable to fetch${NC}")
    echo -e "  ${GREEN}$external_ip${NC}"
    echo
  fi

  if [[ "$show_internal" == "true" ]]; then
    echo -e "${BOLD}${CYAN}Internal IPs:${NC}"
    while IFS=: read -r iface ip; do
      echo -e "  ${YELLOW}$iface${NC}: ${GREEN}$ip${NC}"
    done < <(get_internal_ips_detailed)
    echo
  fi

  if [[ "$show_all" == "true" ]]; then
    echo -e "${BOLD}${CYAN}Gateway:${NC}"
    echo -e "  ${GREEN}$(get_gateway)${NC}"
    echo

    echo -e "${BOLD}${CYAN}DNS Servers:${NC}"
    for dns in $(get_dns_servers); do
      echo -e "  ${GREEN}$dns${NC}"
    done
    echo
  fi
}

# Parse arguments
mode="default"
show_external=true
show_internal=true
show_all=false
copy_to_clipboard=false
json_format=false

while [[ $# -gt 0 ]]; do
  case $1 in
    -e|--external)
      show_external=true
      show_internal=false
      shift
      ;;
    -i|--internal)
      show_external=false
      show_internal=true
      shift
      ;;
    -c|--copy)
      copy_to_clipboard=true
      shift
      ;;
    -j|--json)
      json_format=true
      shift
      ;;
    -a|--all)
      show_all=true
      shift
      ;;
    -h|--help)
      show_help
      exit 0
      ;;
    *)
      echo "${RED}Error: Unknown option: $1${NC}" >&2
      echo "Run 'myip --help' for usage information" >&2
      exit 1
      ;;
  esac
done

# Clipboard helper
clip_set() {
  if command -v xsel &>/dev/null; then
    xsel --input --clipboard
  elif command -v xclip &>/dev/null; then
    xclip -selection clipboard
  fi
}

# Main logic
if [[ "$json_format" == "true" ]]; then
  json_output
elif [[ "$copy_to_clipboard" == "true" ]]; then
  external_ip=$(get_external_ip)
  echo -n "$external_ip" | clip_set
  echo -e "${GREEN}✓${NC} Copied to clipboard: ${BOLD}$external_ip${NC}"
else
  colorized_output "$show_external" "$show_internal" "$show_all"
fi
