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

# Script Name: network-discovery.sh
# Description: Discover devices on local network and highlight the newest device
# Version: 1.0.0
# Dependencies: arp-scan (or nmap), gum (optional but recommended)

# === Configuration ===
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly VERSION="1.0.0"
readonly LOGFILE="${LOGFILE:-/tmp/$(basename "$0" .sh)-$$.log}"

# Ensure log file is writable
touch "$LOGFILE" 2>/dev/null || LOGFILE="/dev/null"
chmod 644 "$LOGFILE" 2>/dev/null || true

# Colors for output
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'

# === Logging Functions ===
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $*" | tee -a "$LOGFILE"
}

log_error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $*" | tee -a "$LOGFILE" >&2
}

log_warn() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $*" | tee -a "$LOGFILE"
}

# === Cleanup Handler ===
TEMP_FILES=()

cleanup() {
    local exit_code=$?

    # Clean temp files
    for file in "${TEMP_FILES[@]}"; do
        [[ -f "$file" ]] && rm -f "$file"
    done

    # Clean log file on successful completion
    if [[ $exit_code -eq 0 ]] && [[ "$LOGFILE" != "/dev/null" ]]; then
        rm -f "$LOGFILE" 2>/dev/null || true
    fi

    exit $exit_code
}

trap cleanup EXIT INT TERM

# === Dependency Checking ===
HAS_GUM=false
HAS_ARP_SCAN=false
SCAN_METHOD=""

check_dependencies() {
    # Check for gum (optional) - check common locations
    if command -v gum &>/dev/null; then
        HAS_GUM=true
    elif [[ -x "$HOME/go/bin/gum" ]]; then
        HAS_GUM=true
        export PATH="$HOME/go/bin:$PATH"
    elif [[ -x "/home/e/go/bin/gum" ]]; then
        HAS_GUM=true
        export PATH="/home/e/go/bin:$PATH"
    fi

    # Check for scanning tools
    if command -v arp-scan &>/dev/null; then
        HAS_ARP_SCAN=true
        SCAN_METHOD="arp-scan"
    elif command -v nmap &>/dev/null; then
        SCAN_METHOD="nmap"
        log_warn "Using nmap (arp-scan recommended for better MAC detection)"
    else
        log_error "No network scanning tool found"
        echo "Please install one of:"
        echo "  sudo apt install arp-scan  (recommended)"
        echo "  sudo apt install nmap"
        return 1
    fi

    return 0
}

# === UI Functions ===
show_header() {
    clear

    if [[ "$HAS_GUM" == "true" ]]; then
        gum style \
            --border thick \
            --border-foreground 12 \
            --align center \
            --width 60 \
            --margin "1" \
            --padding "1 2" \
            "🔍 NETWORK DEVICE DISCOVERY" \
            "" \
            "v${VERSION}" \
            "Scanning local network..."
        echo
    else
        echo -e "${BLUE}╔════════════════════════════════════════════════════╗${NC}"
        echo -e "${BLUE}║${NC}     🔍 ${BOLD}NETWORK DEVICE DISCOVERY${NC}              ${BLUE}║${NC}"
        echo -e "${BLUE}║${NC}                                                    ${BLUE}║${NC}"
        echo -e "${BLUE}║${NC}               v${VERSION}                            ${BLUE}║${NC}"
        echo -e "${BLUE}║${NC}          Scanning local network...                 ${BLUE}║${NC}"
        echo -e "${BLUE}╚════════════════════════════════════════════════════╝${NC}"
        echo
    fi
}

# === Network Functions ===
get_local_network() {
    # Get the default gateway and derive network
    local gateway
    gateway=$(ip route | grep default | awk '{print $3}' | head -n1)

    if [[ -z "$gateway" ]]; then
        log_error "Could not determine default gateway"
        return 1
    fi

    # Extract network (assumes /24)
    local network
    network=$(echo "$gateway" | cut -d. -f1-3)
    echo "${network}.0/24"
}

scan_network_arp_scan() {
    local network="$1"
    local output_file="$2"

    if [[ "$HAS_GUM" == "true" ]]; then
        echo -e "${CYAN}🔍 Scanning network with arp-scan...${NC}"
        (
            sudo arp-scan --interface=eth0 --localnet 2>/dev/null || \
            sudo arp-scan --interface=wlan0 --localnet 2>/dev/null || \
            sudo arp-scan --localnet 2>/dev/null
        ) | tee "$output_file" &

        local scan_pid=$!
        # Spinner options: dot, pulse, points, minidot, line, jump, globe, moon, monkey, meter, hamburger
        gum spin --spinner pulse --title "Scanning local network..." -- bash -c "while kill -0 $scan_pid 2>/dev/null; do sleep 0.1; done"
        wait $scan_pid
    else
        echo -e "${CYAN}⏳ Scanning network with arp-scan...${NC}"
        sudo arp-scan --localnet 2>/dev/null | tee "$output_file"
    fi
}

scan_network_nmap() {
    local network="$1"
    local output_file="$2"

    if [[ "$HAS_GUM" == "true" ]]; then
        echo -e "${CYAN}🔍 Scanning network with nmap...${NC}"
        (
            sudo nmap -sn -PR "$network" 2>/dev/null
        ) | tee "$output_file" &

        local scan_pid=$!
        # Spinner options: dot, pulse, points, minidot, line, jump, globe, moon, monkey, meter, hamburger
        gum spin --spinner pulse --title "Scanning local network..." -- bash -c "while kill -0 $scan_pid 2>/dev/null; do sleep 0.1; done"
        wait $scan_pid
    else
        echo -e "${CYAN}⏳ Scanning network with nmap...${NC}"
        sudo nmap -sn -PR "$network" 2>/dev/null | tee "$output_file"
    fi
}

parse_arp_scan_results() {
    local scan_file="$1"
    local results_file="$2"

    # Parse arp-scan output: IP, MAC, Vendor
    # arp-scan format: 192.168.1.1  aa:bb:cc:dd:ee:ff  Vendor Name
    # Using pipe (|) as delimiter instead of comma to handle vendor names with commas
    grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" "$scan_file" | \
        grep -v "^Interface\|^Starting\|^Ending\|packets received" | \
        awk '{
            ip=$1
            mac=$2
            vendor=$3
            for(i=4;i<=NF;i++) vendor=vendor" "$i
            if(vendor=="") vendor="Unknown"
            print ip"|"mac"|"vendor
        }' > "$results_file"
}

parse_nmap_results() {
    local scan_file="$1"
    local results_file="$2"

    # After nmap scan, check entire ARP cache for all discovered devices
    log "Checking ARP cache for MAC addresses..."

    # Get all IPs from nmap output
    local found_ips=()
    while read -r line; do
        if [[ "$line" =~ "Nmap scan report for" ]]; then
            local ip=$(echo "$line" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}')
            [[ -n "$ip" ]] && found_ips+=("$ip")
        fi
    done < "$scan_file"

    # Now get MAC addresses from ARP cache
    for ip in "${found_ips[@]}"; do
        # Check arp cache
        local arp_line
        arp_line=$(arp -n | grep "^$ip " 2>/dev/null)

        if [[ -n "$arp_line" ]]; then
            # Parse: 10.98.0.1    ether   aa:bb:cc:dd:ee:ff   C   eth0
            local mac
            mac=$(echo "$arp_line" | awk '{print $3}')

            # Try to get vendor info (might need additional lookup)
            local vendor="Unknown"
            if [[ "$mac" =~ ^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$ ]]; then
                # Valid MAC, try to identify device type
                case "${mac:0:8}" in
                    "00:50:56"|"00:0c:29"|"00:05:69") vendor="VMware" ;;
                    "08:00:27") vendor="VirtualBox" ;;
                    "52:54:00") vendor="QEMU/KVM" ;;
                    *) vendor="Device" ;;
                esac
            fi

            echo "${ip},${mac},${vendor}"
        else
            echo "${ip},Unknown,Unknown"
        fi
    done > "$results_file"
}

find_newest_device() {
    local results_file="$1"

    # Get current ARP cache with timestamps
    local newest_ip=""
    local newest_mac=""
    local newest_vendor=""
    local newest_age=999999

    # Read results and check ARP cache age (using pipe delimiter)
    while IFS='|' read -r ip mac vendor; do
        [[ -z "$ip" ]] && continue

        # Check if device is in ARP cache
        if arp -n "$ip" &>/dev/null; then
            # Most recently added device will be at the end of the list
            # We'll use the last device found as "newest"
            newest_ip="$ip"
            newest_mac="$mac"
            newest_vendor="$vendor"
        fi
    done < "$results_file"

    # If no ARP cache method works, just take the last device from scan
    if [[ -z "$newest_ip" ]]; then
        local last_line
        last_line=$(tail -n1 "$results_file")
        newest_ip=$(echo "$last_line" | cut -d'|' -f1)
        newest_mac=$(echo "$last_line" | cut -d'|' -f2)
        newest_vendor=$(echo "$last_line" | cut -d'|' -f3)
    fi

    echo "${newest_ip}|${newest_mac}|${newest_vendor}"
}

display_results() {
    local results_file="$1"
    local newest_device="$2"

    local newest_ip newest_mac newest_vendor
    IFS='|' read -r newest_ip newest_mac newest_vendor <<< "$newest_device"

    echo
    if [[ "$HAS_GUM" == "true" ]]; then
        gum style \
            --border double \
            --border-foreground 10 \
            --padding "1" \
            "📊 Discovered Devices"
        echo
    else
        echo -e "${GREEN}╔══════════════════════════════════════════════════╗${NC}"
        echo -e "${GREEN}║${NC}          📊 Discovered Devices                  ${GREEN}║${NC}"
        echo -e "${GREEN}╚══════════════════════════════════════════════════╝${NC}"
        echo
    fi

    # Header
    printf "${BOLD}%-16s %-20s %-30s${NC}\n" "IP ADDRESS" "MAC ADDRESS" "VENDOR"
    echo "────────────────────────────────────────────────────────────────────"

    # Display all devices - use awk to do ALL the formatting
    local device_count
    device_count=$(wc -l < "$results_file" 2>/dev/null || echo 0)

    # Use awk to format everything directly (avoids pipe/subshell issues)
    awk -F '|' -v newest_ip="$newest_ip" \
        -v MAGENTA="${MAGENTA}" -v CYAN="${CYAN}" -v YELLOW="${YELLOW}" \
        -v GREEN="${GREEN}" -v BOLD="${BOLD}" -v NC="${NC}" \
        '{
            ip=$1
            mac=$2
            vendor=$3

            if (ip == newest_ip) {
                # Newest device - HIGHLIGHT IT!
                printf "%s%s%-16s%s %s%s%-20s%s %s%-30s%s %s⭐ NEWEST%s\n", \
                    BOLD, MAGENTA, ip, NC, \
                    BOLD, CYAN, mac, NC, \
                    YELLOW, vendor, NC, \
                    GREEN, NC
            } else {
                printf "%-16s %-20s %-30s\n", ip, mac, vendor
            }
        }' "$results_file"

    echo
    echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

    # Summary box
    if [[ "$HAS_GUM" == "true" ]]; then
        gum style \
            --border rounded \
            --border-foreground 10 \
            --foreground 10 \
            --padding "1" \
            "✅ Scan Complete!" \
            "" \
            "Total devices found: ${device_count}" \
            "Newest device: ${newest_ip}" \
            "MAC Address: ${newest_mac}" \
            "Vendor: ${newest_vendor}"
    else
        echo
        echo -e "${GREEN}✅ Scan Complete!${NC}"
        echo -e "${BOLD}Total devices found:${NC} ${device_count}"
        echo
        echo -e "${BOLD}${MAGENTA}Newest Device:${NC}"
        echo -e "  ${BOLD}IP:${NC}     ${newest_ip}"
        echo -e "  ${BOLD}MAC:${NC}    ${newest_mac}"
        echo -e "  ${BOLD}Vendor:${NC} ${newest_vendor}"
    fi

    echo
}

# === Usage Function ===
usage() {
    cat << EOF
Usage: $(basename "$0") [OPTIONS]

Description:
    Scan local network for devices and highlight the newest device

Options:
    -h, --help      Show this help message
    -v, --verbose   Enable verbose output

Examples:
    sudo $(basename "$0")
    sudo $(basename "$0") --verbose

Requirements:
    - Must run with sudo (for network scanning)
    - arp-scan or nmap installed
    - gum (optional, for enhanced UI)

EOF
}

# === Main Logic ===
main() {
    # Parse arguments
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -h|--help)
                usage
                exit 0
                ;;
            -v|--verbose)
                set -x
                shift
                ;;
            *)
                log_error "Unknown option: $1"
                usage
                exit 1
                ;;
        esac
    done

    # Check if running as root
    if [[ $EUID -ne 0 ]]; then
        log_error "This script must be run as root (for network scanning)"
        echo "Please run: sudo $0"
        exit 1
    fi

    # Check dependencies
    check_dependencies || exit 2

    # Show header
    show_header

    # Show arp-scan tip if using nmap
    if [[ "$SCAN_METHOD" == "nmap" ]]; then
        echo -e "${YELLOW}💡 Tip: Install arp-scan for better device detection${NC}"
        echo -e "${YELLOW}   Command: sudo apt install arp-scan${NC}"
        echo
    fi

    # Get local network
    log "Detecting local network..."
    local network
    network=$(get_local_network)
    log "Network: $network"
    echo -e "${BLUE}ℹ️  Network: ${BOLD}$network${NC}"
    echo

    # Create temp files
    local scan_file results_file
    scan_file=$(mktemp)
    results_file=$(mktemp)
    # Only add scan_file to cleanup - we need results_file until display is done
    TEMP_FILES+=("$scan_file")

    # Scan network
    log "Scanning network with $SCAN_METHOD"
    if [[ "$SCAN_METHOD" == "arp-scan" ]]; then
        scan_network_arp_scan "$network" "$scan_file"
        parse_arp_scan_results "$scan_file" "$results_file"
    else
        scan_network_nmap "$network" "$scan_file"
        parse_nmap_results "$scan_file" "$results_file"
    fi

    # Check if we found any devices
    if [[ ! -s "$results_file" ]]; then
        log_error "No devices found on network"
        exit 1
    fi

    # Find newest device
    log "Analyzing results..."
    local newest_device
    newest_device=$(find_newest_device "$results_file")

    # Display results
    display_results "$results_file" "$newest_device"

    # Clean up results file after display
    rm -f "$results_file"

    log "✅ Network discovery complete"
}

# Run main function
main "$@"
