#!/bin/zsh
# Advanced Wi-Fi MAC spoofing script for macOS
# Automatically detects phone hotspot MAC or allows manual input
# Usage:
#   spoof-wifi-mac.sh                    # auto-detect connected hotspot MAC
#   spoof-wifi-mac.sh --phone-mac        # detect phone MAC from hotspot
#   spoof-wifi-mac.sh AA:BB:CC:DD:EE:FF  # set specific MAC
#   spoof-wifi-mac.sh --revert           # restore original MAC

set -euo pipefail

# Get absolute path to script
if [ -n "${ZSH_VERSION:-}" ]; then
  SCRIPT_PATH="${0:A}"
else
  SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
fi
# Fallback if still empty
if [ -z "$SCRIPT_PATH" ] || [ ! -f "$SCRIPT_PATH" ]; then
  SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
fi

STATE_FILE="/tmp/wifi_mac_spoof_state"
ORIGINAL_MAC_FILE="/tmp/wifi_mac_original"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

require_root() {
  if [ "$EUID" -ne 0 ] && [ "$(id -u)" -ne 0 ]; then
    echo -e "${YELLOW}Re-running with sudo...${NC}"
    exec sudo -E "$0" "${@}"
  fi
}

detect_wifi_if() {
  local iface
  iface=$(networksetup -listallhardwareports | awk '/Wi-Fi/{getline; print $2; exit}')
  if [ -z "$iface" ]; then
    echo -e "${RED}Error: Could not detect Wi-Fi interface${NC}"
    exit 1
  fi
  echo "$iface"
}

get_current_mac() {
  local iface="$1"
  ifconfig "$iface" 2>/dev/null | awk '/ether/{print $2; exit}' || echo ""
}

get_connected_network() {
  local iface="$1"
  /System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I 2>/dev/null | awk '/ SSID:/ {print substr($0, index($0,$2))}' || echo ""
}

get_connected_bssid() {
  local iface="$1"
  /System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I 2>/dev/null | awk '/ BSSID:/ {print $2}' || echo ""
}

detect_phone_hotspot_mac() {
  local iface="$1"
  local bssid
  
  echo -e "${BLUE}Detecting connected hotspot MAC...${NC}"
  
  bssid=$(get_connected_bssid "$iface")
  if [ -z "$bssid" ] || [ "$bssid" = "none" ]; then
    echo -e "${YELLOW}Warning: Not connected to Wi-Fi or cannot detect BSSID${NC}"
    return 1
  fi
  
  echo -e "${GREEN}Found hotspot BSSID: $bssid${NC}"
  echo "$bssid"
  return 0
}

validate_mac() {
  local mac="$1"
  if ! [[ "$mac" =~ ^([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}$ ]]; then
    echo -e "${RED}Invalid MAC format: $mac (expected AA:BB:CC:DD:EE:FF)${NC}"
    exit 1
  fi
}

power_wifi() {
  local iface="$1"
  local state="$2" # on|off
  networksetup -setairportpower "$iface" "$state" 2>/dev/null || true
  sleep 1
}

save_original_mac() {
  local iface="$1"
  local mac="$2"
  
  if [ ! -f "$ORIGINAL_MAC_FILE" ]; then
    echo "$iface|$mac" > "$ORIGINAL_MAC_FILE"
    echo -e "${GREEN}Saved original MAC for permanent restore: $mac${NC}"
  fi
}

check_sip_status() {
  local sip_status
  sip_status=$(csrutil status 2>/dev/null | grep -i "enabled" || echo "unknown")
  if [[ "$sip_status" == *"enabled"* ]]; then
    return 0  # SIP enabled
  else
    return 1  # SIP disabled or unknown
  fi
}

set_mac() {
  local iface="$1"
  local mac="$2"

  local current_mac
  current_mac=$(get_current_mac "$iface")
  
  if [ -z "$current_mac" ]; then
    echo -e "${RED}Error: Cannot read current MAC address${NC}"
    exit 1
  fi

  echo -e "${BLUE}Current MAC: $current_mac${NC}"
  echo -e "${BLUE}Target MAC:  $mac${NC}"
  
  if [ "$current_mac" = "$mac" ]; then
    echo -e "${YELLOW}MAC already set to target value${NC}"
    return 0
  fi

  # Check SIP status
  if check_sip_status; then
    echo -e "${YELLOW}⚠ System Integrity Protection (SIP) is enabled${NC}"
    echo -e "${YELLOW}MAC spoofing may be blocked on Apple Silicon with SIP enabled${NC}"
  fi

  # Save original MAC if not saved
  save_original_mac "$iface" "$current_mac"
  
  # Save for revert
  echo "$iface $current_mac" > "$STATE_FILE"

  echo -e "${YELLOW}Turning Wi-Fi off...${NC}"
  power_wifi "$iface" off

  echo -e "${YELLOW}Setting MAC to $mac...${NC}"
  
  # Try ifconfig method
  local success=false
  if ifconfig "$iface" ether "$mac" 2>/dev/null; then
    success=true
  fi
  
  if [ "$success" = false ]; then
    echo -e "${RED}✗ Error: Failed to set MAC address${NC}"
    echo ""
    echo -e "${BLUE}=== РЕШЕНИЕ ПРОБЛЕМЫ ===${NC}"
    echo ""
    
    if check_sip_status; then
      echo -e "${YELLOW}На Apple Silicon (M1/M2/M3) с включенным SIP подмена MAC заблокирована${NC}"
      echo ""
      echo -e "${YELLOW}Варианты решения:${NC}"
      echo "1. Отключить SIP (НЕ рекомендуется - снижает безопасность)"
      echo "   - Перезагрузите в Recovery Mode (Cmd+R)"
      echo "   - Утилиты → Терминал → csrutil disable"
      echo "   - Перезагрузите Mac"
      echo ""
      echo "2. Использовать альтернативные методы:"
      echo "   • VPN на телефоне (рекомендуется)"
      echo "   • USB Tethering вместо Wi-Fi hotspot"
      echo "   • Bluetooth Tethering"
      echo ""
      echo -e "${BLUE}Важно:${NC}"
      echo "Оператор сотовой связи видит IMEI телефона, а не MAC MacBook."
      echo "MAC клиента виден только на уровне локальной Wi-Fi сети."
      echo "Подмена MAC не меняет идентификацию на уровне оператора."
    else
      echo -e "${YELLOW}Интерфейс может не поддерживать подмену MAC${NC}"
      echo -e "${YELLOW}Или требуется дополнительная настройка${NC}"
    fi
    
    power_wifi "$iface" on
    exit 1
  fi

  echo -e "${YELLOW}Turning Wi-Fi on...${NC}"
  power_wifi "$iface" on
  
  sleep 2

  local new_mac
  new_mac=$(get_current_mac "$iface")
  
  if [ "$new_mac" = "$mac" ]; then
    echo -e "${GREEN}✓ Success! MAC changed to: $new_mac${NC}"
  else
    echo -e "${RED}⚠ Warning: MAC may not have changed${NC}"
    echo -e "${YELLOW}Current MAC: $new_mac${NC}"
    echo -e "${YELLOW}Target MAC:  $mac${NC}"
    echo -e "${YELLOW}This may require disabling SIP or using a different method${NC}"
  fi
}

revert_mac() {
  local iface
  local original_mac
  
  if [ -f "$STATE_FILE" ]; then
    read iface original_mac < "$STATE_FILE"
  elif [ -f "$ORIGINAL_MAC_FILE" ]; then
    local saved
    saved=$(cat "$ORIGINAL_MAC_FILE")
    iface=$(echo "$saved" | cut -d'|' -f1)
    original_mac=$(echo "$saved" | cut -d'|' -f2)
  else
    echo -e "${RED}No saved MAC found. Cannot revert.${NC}"
    exit 1
  fi
  
  if [ -z "${iface:-}" ] || [ -z "${original_mac:-}" ]; then
    echo -e "${RED}State file is corrupted. Delete $STATE_FILE and $ORIGINAL_MAC_FILE${NC}"
    exit 1
  fi
  
  echo -e "${BLUE}Restoring MAC for $iface to $original_mac...${NC}"
  power_wifi "$iface" off
  ifconfig "$iface" ether "$original_mac" 2>/dev/null || {
    echo -e "${RED}Failed to restore MAC${NC}"
    power_wifi "$iface" on
    exit 1
  }
  power_wifi "$iface" on
  sleep 2
  
  rm -f "$STATE_FILE"
  local current
  current=$(get_current_mac "$iface")
  echo -e "${GREEN}✓ Reverted. Current MAC: $current${NC}"
}

show_instructions() {
  echo -e "${BLUE}=== ИНСТРУКЦИИ ПО ПОЛУЧЕНИЮ MAC ТЕЛЕФОНА ===${NC}"
  echo ""
  echo -e "${YELLOW}iPhone:${NC}"
  echo "1. Настройки → Wi-Fi"
  echo "2. Нажмите (i) рядом с сетью"
  echo "3. Отключите 'Частный Wi-Fi адрес' (Private Wi-Fi Address)"
  echo "4. MAC-адрес будет показан как 'Адрес Wi-Fi'"
  echo ""
  echo -e "${YELLOW}Android:${NC}"
  echo "1. Настройки → О телефоне → Статус"
  echo "2. Найдите 'MAC-адрес Wi-Fi'"
  echo ""
  echo -e "${YELLOW}Альтернативный способ (если подключены к hotspot):${NC}"
  echo "Скрипт может автоматически определить MAC точки доступа"
  echo "Используйте: $0 --phone-mac"
  echo ""
}

main() {
  # Check if we need root and restart with sudo if needed
  # Skip check for help/instructions commands that don't need root
  local arg="${1:-}"
  local needs_root=false
  
  if [ "$arg" != "--help" ] && [ "$arg" != "-h" ] && [ "$arg" != "--instructions" ]; then
    needs_root=true
  fi
  
  if [ "$needs_root" = true ] && [ "$(id -u)" -ne 0 ]; then
    echo -e "${YELLOW}Re-running with sudo...${NC}"
    exec sudo -E "$SCRIPT_PATH" "${@}"
    exit 0
  fi

  if [ "$arg" = "--help" ] || [ "$arg" = "-h" ]; then
    echo "Usage: $0 [OPTIONS] [MAC_ADDRESS]"
    echo ""
    echo "Options:"
    echo "  --phone-mac    Auto-detect phone hotspot MAC"
    echo "  --revert       Restore original MAC"
    echo "  --instructions Show instructions for finding phone MAC"
    echo "  --help         Show this help"
    echo ""
    echo "Examples:"
    echo "  $0                          # Interactive mode"
    echo "  $0 --phone-mac              # Auto-detect hotspot MAC"
    echo "  $0 AA:BB:CC:DD:EE:FF       # Set specific MAC"
    echo "  $0 --revert                 # Restore original"
    exit 0
  fi

  if [ "$arg" = "--instructions" ]; then
    show_instructions
    exit 0
  fi

  if [ "$arg" = "--revert" ]; then
    revert_mac
    exit 0
  fi

  local iface
  iface=$(detect_wifi_if)
  echo -e "${GREEN}Wi-Fi interface: $iface${NC}"

  local target_mac=""
  
  if [ "$arg" = "--phone-mac" ]; then
    target_mac=$(detect_phone_hotspot_mac "$iface")
    if [ -z "$target_mac" ]; then
      echo -e "${RED}Could not detect phone hotspot MAC${NC}"
      echo -e "${YELLOW}Make sure you're connected to phone hotspot and try manual input${NC}"
      show_instructions
      exit 1
    fi
  elif [ -n "$arg" ]; then
    target_mac="$arg"
  else
    # Try auto-detect first
    local detected
    detected=$(detect_phone_hotspot_mac "$iface" 2>/dev/null || echo "")
    
    if [ -n "$detected" ]; then
      echo -e "${GREEN}Detected hotspot MAC: $detected${NC}"
      read "confirm?Use this MAC? (y/n): "
      if [[ "$confirm" =~ ^[Yy] ]]; then
        target_mac="$detected"
      else
        read "target_mac?Enter phone Wi-Fi MAC (AA:BB:CC:DD:EE:FF): "
      fi
    else
      show_instructions
      read "target_mac?Enter phone Wi-Fi MAC (AA:BB:CC:DD:EE:FF): "
    fi
  fi

  if [ -z "$target_mac" ]; then
    echo -e "${RED}No MAC address provided${NC}"
    exit 1
  fi

  validate_mac "$target_mac"

  set_mac "$iface" "$target_mac"
  
  echo ""
  echo -e "${BLUE}=== ВАЖНО ===${NC}"
  echo -e "${YELLOW}• MAC сбросится после перезагрузки или переподключения Wi-Fi${NC}"
  echo -e "${YELLOW}• Используйте '$0 --revert' для восстановления${NC}"
  echo -e "${YELLOW}• Для постоянной подмены может потребоваться отключение SIP${NC}"
  echo -e "${YELLOW}• Оператор видит трафик через точку доступа, MAC клиента виден только на уровне Wi-Fi${NC}"
}

main "$@"
