#!/bin/bash

# ==============================================================================
#  Hadoop Handler — Single-Node Cluster Control Panel (Linux & macOS)
#  Developer: Aditya Pidurkar (github.com/itsadityapidurkar)
# ==============================================================================

CURRENT_VERSION="1.1.0"

# Colors for terminal output
RED='\033[0;31m'
BRED='\033[1;31m'
GREEN='\033[0;32m'
BGREEN='\033[1;32m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BCYAN='\033[1;36m'
YELLOW='\033[1;33m'
GRAY='\033[90m'
NC='\033[0m' # No Color

DIVIDER="${GRAY}─────────────────────────────────────────────────────────────────${NC}"

# Detect OS
OS_NAME=$(uname -s)

# Portable symlink resolution to find original install directory
TARGET_FILE="${BASH_SOURCE[0]}"
while [ -h "$TARGET_FILE" ]; do
    DIR="$(dirname "$TARGET_FILE")"
    TARGET_FILE="$(readlink "$TARGET_FILE")"
    [[ "$TARGET_FILE" != /* ]] && TARGET_FILE="$DIR/$TARGET_FILE"
done
SCRIPT_DIR="$(cd -P "$(dirname "$TARGET_FILE")" && pwd)"

# Send native desktop notification
send_notification() {
    local title="$1"
    local message="$2"
    if [ "$OS_NAME" = "Linux" ] && command -v notify-send >/dev/null 2>&1; then
        notify-send "$title" "$message" 2>/dev/null || true
    elif [ "$OS_NAME" = "Darwin" ]; then
        osascript -e "display notification \"$message\" with title \"$title\"" 2>/dev/null || true
    fi
}

# Smooth download progress with Python or curl fallback
download_file() {
    local url="$1"
    local dest="$2"
    local title="${3:-Downloading}"

    if command -v python3 >/dev/null 2>&1; then
        python3 - << EOF
import os, sys, time, urllib.request

url = "$url"
dest = "$dest"
title = "$title"

headers = {'User-Agent': 'Hadoop-Handler/$CURRENT_VERSION'}
resume_byte_pos = 0
if os.path.exists(dest):
    resume_byte_pos = os.path.getsize(dest)

req = urllib.request.Request(url, headers=headers)
if resume_byte_pos > 0:
    req.add_header("Range", f"bytes={resume_byte_pos}-")

try:
    with urllib.request.urlopen(req, timeout=30) as resp:
        content_length = resp.headers.get('Content-Length')
        if resp.status == 206:
            total_size = resume_byte_pos + int(content_length) if content_length else 0
            mode = 'ab'
            downloaded = resume_byte_pos
        else:
            total_size = int(content_length) if content_length else 0
            mode = 'wb'
            downloaded = 0

        start_time = time.time()
        chunk_size = 131072 # 128 KB
        bar_width = 24

        print(f"        {title}...")
        with open(dest, mode) as f:
            while True:
                chunk = resp.read(chunk_size)
                if not chunk:
                    break
                f.write(chunk)
                downloaded += len(chunk)
                elapsed = time.time() - start_time
                speed = (downloaded - resume_byte_pos) / elapsed if elapsed > 0 else 0

                if total_size > 0:
                    pct = min(100.0, (downloaded / total_size) * 100)
                    filled = int(bar_width * downloaded // total_size)
                    bar = '█' * filled + '░' * (bar_width - filled)
                    eta = (total_size - downloaded) / speed if speed > 0 else 0
                    eta_str = f"{int(eta // 60):02d}:{int(eta % 60):02d}"
                    sys.stdout.write(f"\r        [{bar}] {pct:5.1f}% ({downloaded/(1024*1024):.1f}/{total_size/(1024*1024):.1f} MB) {speed/(1024*1024):.1f} MB/s ETA {eta_str}")
                else:
                    sys.stdout.write(f"\r        Downloaded: {downloaded/(1024*1024):.1f} MB ({speed/(1024*1024):.1f} MB/s)")
                sys.stdout.flush()
        print()
    sys.exit(0)
except Exception as e:
    sys.stderr.write(f"\n        [!] Python download interrupted ({e}), falling back to curl...\n")
    sys.exit(1)
EOF
        if [ $? -eq 0 ] && [ -s "$dest" ]; then
            return 0
        fi
    fi

    # Fallback to curl with progress bar
    if command -v curl >/dev/null 2>&1; then
        echo -e "        Downloading via curl (progress bar enabled)..."
        curl -# -L -C - -o "$dest" "$url"
        return $?
    elif command -v wget >/dev/null 2>&1; then
        wget --progress=bar:force -c -O "$dest" "$url"
        return $?
    else
        echo -e "  ${RED}[!] Neither python3, curl, nor wget found.${NC}"
        return 1
    fi
}

# Check PyPI / GitHub for newer releases and display non-intrusive banner
check_version_banner() {
    local cache_file="$HOME/.hadoop-handler/.version_cache"
    local now=$(date +%s)
    local last_check=0

    mkdir -p "$HOME/.hadoop-handler" 2>/dev/null || true
    if [ -f "$cache_file" ]; then
        last_check=$(stat -c %Y "$cache_file" 2>/dev/null || stat -f %m "$cache_file" 2>/dev/null || echo 0)
    fi

    # Check at most once every 12 hours (43200 seconds) in the background
    if [ $((now - last_check)) -gt 43200 ]; then
        (
            local latest=$(curl -s --max-time 1.5 https://api.github.com/repos/itsadityapidurkar/hadoop-handler/releases/latest 2>/dev/null | grep '"tag_name":' | sed -E 's/.*"v?([^"]+)".*/\1/' || echo "")
            if [ -n "$latest" ]; then
                echo "$latest" > "$cache_file"
            else
                latest=$(curl -s --max-time 1.5 https://pypi.org/pypi/hadoop-handler/json 2>/dev/null | grep -o '"version":"[^"]*"' | head -n 1 | cut -d'"' -f4 || echo "")
                [ -n "$latest" ] && echo "$latest" > "$cache_file"
            fi
        ) 2>/dev/null &
    fi

    if [ -f "$cache_file" ]; then
        local remote_ver=$(cat "$cache_file" 2>/dev/null | tr -d '[:space:]')
        if [ -n "$remote_ver" ] && [ "$remote_ver" != "$CURRENT_VERSION" ]; then
            echo -e "  ${YELLOW}* Note: Update available: ${CURRENT_VERSION} -> ${remote_ver}.${NC}"
            echo -e "    Run ${CYAN}hadoop-handler update${NC} to upgrade."
            echo -e "$DIVIDER"
        fi
    fi
}

# Load environment variables dynamically within the script execution context
load_env() {
    if [ -z "$HADOOP_HOME" ]; then
        if [ -d "/opt/hadoop" ]; then
            export HADOOP_HOME="/opt/hadoop"
        elif [ -d "/Users/Shared/hadoop" ]; then
            export HADOOP_HOME="/Users/Shared/hadoop"
        elif [ -d "$HOME/hadoop" ]; then
            export HADOOP_HOME="$HOME/hadoop"
        fi
    fi
    if [ -n "$HADOOP_HOME" ]; then
        export HADOOP_CONF_DIR="$HADOOP_HOME/etc/hadoop"
        export PATH="$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin"
        # Detect Java Home if not set
        if [ -z "$JAVA_HOME" ]; then
            if [ "$OS_NAME" = "Linux" ]; then
                if command -v java >/dev/null 2>&1; then
                    export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
                fi
            elif [ "$OS_NAME" = "Darwin" ]; then
                if command -v java >/dev/null 2>&1; then
                    export JAVA_HOME=$(/usr/libexec/java_home -v 21)
                fi
            fi
        fi
    fi
}

pause_screen() {
    echo -e "\n$DIVIDER"
    echo -ne "  ${YELLOW}Press [Enter] to return to the main menu...${NC}"
    read -r
}

# 1. Install Hadoop
install_hadoop() {
    clear
    echo -e "$DIVIDER"
    echo -e "  ${BCYAN}ACTION: Installing Apache Hadoop 3.4.2${NC}"
    echo -e "$DIVIDER\n"
    
    # Check for Java 21
    echo -e "  ${GRAY}[1/8]${NC} Checking for Java 21 compatibility..."
    JAVA_VER=""
    if command -v java >/dev/null 2>&1; then
        JAVA_VER=$(java -version 2>&1 | head -n 1 | awk -F '"' '{print $2}')
        echo -e "        Found Java: ${GREEN}${JAVA_VER}${NC}"
    fi

    if [[ "$JAVA_VER" == 21* ]]; then
        echo -e "        Java 21 check: ${GREEN}Success${NC}"
    else
        echo -e "        Java 21 not found. Triggering automated installation..."
        if [ "$OS_NAME" = "Linux" ]; then
            if command -v apt-get >/dev/null 2>&1; then
                echo -e "        Running: ${GRAY}sudo apt update && sudo apt install openjdk-21-jdk -y${NC}"
                sudo apt-get update
                sudo apt-get install openjdk-21-jdk -y || { echo -e "  ${RED}[!] Java installation failed.${NC}"; return 1; }
            elif command -v dnf >/dev/null 2>&1; then
                echo -e "        Running: ${GRAY}sudo dnf install java-21-openjdk-devel -y${NC}"
                sudo dnf install java-21-openjdk-devel -y || { echo -e "  ${RED}[!] Java installation failed.${NC}"; return 1; }
            elif command -v yum >/dev/null 2>&1; then
                echo -e "        Running: ${GRAY}sudo yum install java-21-openjdk-devel -y${NC}"
                sudo yum install java-21-openjdk-devel -y || { echo -e "  ${RED}[!] Java installation failed.${NC}"; return 1; }
            elif command -v pacman >/dev/null 2>&1; then
                echo -e "        Running: ${GRAY}sudo pacman -S jre21-openjdk jdk21-openjdk --noconfirm${NC}"
                sudo pacman -S jre21-openjdk jdk21-openjdk --noconfirm || { echo -e "  ${RED}[!] Java installation failed.${NC}"; return 1; }
            else
                echo -e "  ${RED}[!] Supported package manager not found. Please install Java 21 manually.${NC}"
                return 1
            fi
        elif [ "$OS_NAME" = "Darwin" ]; then
            if command -v brew >/dev/null 2>&1; then
                echo -e "        Running: ${GRAY}brew install openjdk@21${NC}"
                brew install openjdk@21 || { echo -e "  ${RED}[!] Java installation failed.${NC}"; return 1; }
                sudo ln -sfn /usr/local/opt/openjdk@21/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-21.jdk || true
            else
                echo -e "  ${RED}[!] Homebrew not found. Please install Homebrew or install Java 21 manually.${NC}"
                return 1
            fi
        else
            echo -e "  ${RED}[!] Unsupported operating system. Please install Java 21 manually.${NC}"
            return 1
        fi
    fi

    # Determine Java Home dynamically
    DETECTED_JAVA_HOME=""
    if [ "$OS_NAME" = "Linux" ]; then
        DETECTED_JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
    elif [ "$OS_NAME" = "Darwin" ]; then
        DETECTED_JAVA_HOME=$(/usr/libexec/java_home -v 21)
    fi
    echo -e "        Detected JAVA_HOME: ${GREEN}${DETECTED_JAVA_HOME}${NC}"

    # Target Locations
    HADOOP_DEST="/opt/hadoop"
    HADOOP_DATA_DIR="/opt/hadoop_data"
    HADOOP_TMP_DIR="/opt/hadoop_tmp"
    HADOOP_TAR="hadoop-3.4.2.tar.gz"
    DOWNLOAD_URL="https://archive.apache.org/dist/hadoop/common/hadoop-3.4.2/${HADOOP_TAR}"

    if [ "$OS_NAME" = "Darwin" ]; then
        if [[ "$HOME" == *" "* ]]; then
            HADOOP_DEST="/Users/Shared/hadoop"
            HADOOP_DATA_DIR="/Users/Shared/hadoop_data"
            HADOOP_TMP_DIR="/Users/Shared/hadoop_tmp"
        else
            HADOOP_DEST="$HOME/hadoop"
            HADOOP_DATA_DIR="$HOME/hadoopdata"
            HADOOP_TMP_DIR="$HOME/hadooptmp"
        fi
    fi

    # Create Directories
    echo -e "\n  ${GRAY}[2/8]${NC} Creating required system directories..."
    mkdir -p ~/Downloads
    if [ "$OS_NAME" = "Linux" ] && [[ "$HOME" == *" "* ]]; then
        sudo mkdir -p "${HADOOP_DATA_DIR}/namenode"
        sudo mkdir -p "${HADOOP_DATA_DIR}/datanode"
        sudo mkdir -p "${HADOOP_TMP_DIR}"
        sudo chown -R $USER:$USER "${HADOOP_DATA_DIR}" "${HADOOP_TMP_DIR}"
    else
        mkdir -p "${HADOOP_DATA_DIR}/namenode"
        mkdir -p "${HADOOP_DATA_DIR}/datanode"
        mkdir -p "${HADOOP_TMP_DIR}"
    fi

    # Download Hadoop 3.4.2 with smooth progress bar
    echo -e "\n  ${GRAY}[3/8]${NC} Retrieving Apache Hadoop 3.4.2 tarball..."
    if [ -f "$HOME/Downloads/${HADOOP_TAR}" ]; then
        echo -e "        ${HADOOP_TAR} already cached in ~/Downloads. Skipping download."
    else
        download_file "${DOWNLOAD_URL}" "$HOME/Downloads/${HADOOP_TAR}" "Retrieving Apache Hadoop 3.4.2 tarball" || {
            echo -e "  ${RED}[!] Download failed.${NC}"
            rm -f "$HOME/Downloads/${HADOOP_TAR}"
            return 1
        }
        send_notification "Hadoop Handler" "Apache Hadoop 3.4.2 tarball downloaded successfully."
    fi

    # Extract and Install
    echo -e "\n  ${GRAY}[4/8]${NC} Extracting and relocating binaries..."
    if [ "$OS_NAME" = "Linux" ]; then
        if [ -d "${HADOOP_DEST}" ]; then
            echo -e "        Removing existing directory at ${HADOOP_DEST}..."
            sudo rm -rf "${HADOOP_DEST}"
        fi
        sudo tar -xzf "$HOME/Downloads/${HADOOP_TAR}" -C /opt || { echo -e "  ${RED}[!] Extraction failed. Tarball may be corrupted.${NC}"; return 1; }
        sudo mv /opt/hadoop-3.4.2 "${HADOOP_DEST}"
        sudo chown -R $USER:$USER "${HADOOP_DEST}"
    else # macOS
        if [ -d "${HADOOP_DEST}" ]; then
            echo -e "        Removing existing directory at ${HADOOP_DEST}..."
            rm -rf "${HADOOP_DEST}"
        fi
        if [[ "$HOME" == *" "* ]]; then
            tar -xzf "$HOME/Downloads/${HADOOP_TAR}" -C /Users/Shared || { echo -e "  ${RED}[!] Extraction failed. Tarball may be corrupted.${NC}"; return 1; }
            mv /Users/Shared/hadoop-3.4.2 "${HADOOP_DEST}"
        else
            tar -xzf "$HOME/Downloads/${HADOOP_TAR}" -C "$HOME/" || { echo -e "  ${RED}[!] Extraction failed. Tarball may be corrupted.${NC}"; return 1; }
            mv "$HOME/hadoop-3.4.2" "${HADOOP_DEST}"
        fi
    fi
    echo -e "        Extraction completed successfully."
    send_notification "Hadoop Handler" "Apache Hadoop 3.4.2 binaries extracted."

    # Configure SSH
    echo -e "\n  ${GRAY}[5/8]${NC} Configuring passwordless SSH keys..."
    if [ ! -f ~/.ssh/id_rsa ]; then
        echo -e "        Generating new SSH keypair..."
        ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N "" || { echo -e "  ${RED}[!] SSH key generation failed.${NC}"; return 1; }
    fi
    
    # Avoid duplicating authorized_keys entry
    touch ~/.ssh/authorized_keys
    if ! grep -q "$(cat ~/.ssh/id_rsa.pub)" ~/.ssh/authorized_keys 2>/dev/null; then
        cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
    fi
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/authorized_keys
    
    # Add localhost to known_hosts to prevent prompts
    if ! ssh-keygen -F localhost >/dev/null 2>&1; then
        ssh-keyscan -H localhost >> ~/.ssh/known_hosts 2>/dev/null
    fi

    if [ "$OS_NAME" = "Darwin" ]; then
        echo -e "        ${YELLOW}Note for macOS:${NC} Ensure 'Remote Login' is enabled in sharing settings."
    fi

    # Configure Environment Variables
    echo -e "\n  ${GRAY}[6/8]${NC} Registering path variables in shell configuration..."
    SHELL_CONFIG=""
    if [[ "$SHELL" == */zsh ]]; then
        SHELL_CONFIG="$HOME/.zshrc"
    else
        SHELL_CONFIG="$HOME/.bashrc"
    fi

    ENV_MARKER="# --- HADOOP HANDLER ENVIRONMENT VARIABLES ---"
    if grep -q "$ENV_MARKER" "${SHELL_CONFIG}" 2>/dev/null; then
        echo -e "        Environment variables already present in ${SHELL_CONFIG}. Skipping duplicate entry."
    else
        cat << EOF >> "${SHELL_CONFIG}"

$ENV_MARKER
export JAVA_HOME="${DETECTED_JAVA_HOME}"
export HADOOP_HOME="${HADOOP_DEST}"
export HADOOP_CONF_DIR="\${HADOOP_HOME}/etc/hadoop"
export HADOOP_COMMON_HOME="\${HADOOP_HOME}"
export HADOOP_HDFS_HOME="\${HADOOP_HOME}"
export HADOOP_MAPRED_HOME="\${HADOOP_HOME}"
export YARN_HOME="\${HADOOP_HOME}"
export HADOOP_COMMON_LIB_NATIVE_DIR="\${HADOOP_HOME}/lib/native"
export PATH="\$PATH:\$HADOOP_HOME/bin:\$HADOOP_HOME/sbin"
EOF
        echo -e "        Variables appended to ${SHELL_CONFIG}."
    fi

    # Configure XML Configuration Files
    echo -e "\n  ${GRAY}[7/8]${NC} Building cluster configuration files..."
    CONF_DIR="${HADOOP_DEST}/etc/hadoop"
    LOCAL_CONF_DIR="${HADOOP_HANDLER_CONF_DIR:-${SCRIPT_DIR}/configs}"

    if [ -d "$LOCAL_CONF_DIR" ]; then
        echo -e "        Loading XML templates from local configs directory..."
        cp "${LOCAL_CONF_DIR}/core-site.xml" "${CONF_DIR}/"
        cp "${LOCAL_CONF_DIR}/hdfs-site.xml" "${CONF_DIR}/"
        cp "${LOCAL_CONF_DIR}/mapred-site.xml" "${CONF_DIR}/"
        cp "${LOCAL_CONF_DIR}/yarn-site.xml" "${CONF_DIR}/"
        cp "${LOCAL_CONF_DIR}/workers" "${CONF_DIR}/"
        
        # Replace template markers with space-free resolved paths
        sed -i.bak "s|/home/YOUR_USERNAME/hadooptmp|${HADOOP_TMP_DIR}|g" "${CONF_DIR}/core-site.xml" || \
        sed -i "" "s|/home/YOUR_USERNAME/hadooptmp|${HADOOP_TMP_DIR}|g" "${CONF_DIR}/core-site.xml"
        
        sed -i.bak "s|file:///home/YOUR_USERNAME/hadoopdata|file://${HADOOP_DATA_DIR}|g" "${CONF_DIR}/hdfs-site.xml" || \
        sed -i "" "s|file:///home/YOUR_USERNAME/hadoopdata|file://${HADOOP_DATA_DIR}|g" "${CONF_DIR}/hdfs-site.xml"
        
        rm -f "${CONF_DIR}/core-site.xml.bak" "${CONF_DIR}/hdfs-site.xml.bak"
    else
        echo -e "        ${YELLOW}[!] Local templates missing. Generating fallback configurations...${NC}"
        # core-site.xml
        cat << EOF > "${CONF_DIR}/core-site.xml"
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>${HADOOP_TMP_DIR}</value>
    </property>
</configuration>
EOF

        # hdfs-site.xml
        cat << EOF > "${CONF_DIR}/hdfs-site.xml"
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file://${HADOOP_DATA_DIR}/namenode</value>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file://${HADOOP_DATA_DIR}/datanode</value>
    </property>
</configuration>
EOF

        # workers
        echo "localhost" > "${CONF_DIR}/workers"

        # mapred-site.xml
        cat << EOF > "${CONF_DIR}/mapred-site.xml"
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
    <property>
        <name>mapreduce.application.classpath</name>
        <value>\$HADOOP_MAPRED_HOME/share/hadoop/mapreduce/*:\$HADOOP_MAPRED_HOME/share/hadoop/mapreduce/lib/*</value>
    </property>
</configuration>
EOF

        # yarn-site.xml
        cat << EOF > "${CONF_DIR}/yarn-site.xml"
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
    <property>
        <name>yarn.nodemanager.env-whitelist</name>
        <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value>
    </property>
</configuration>
EOF
    fi

    # Configure hadoop-env.sh
    sed -i.bak "s|^# export JAVA_HOME=.*|export JAVA_HOME=${DETECTED_JAVA_HOME}|g" "${CONF_DIR}/hadoop-env.sh" || \
    sed -i "" "s|^# export JAVA_HOME=.*|export JAVA_HOME=${DETECTED_JAVA_HOME}|g" "${CONF_DIR}/hadoop-env.sh"

    # Format NameNode
    echo -e "\n  ${GRAY}[8/8]${NC} Formatting HDFS NameNode system..."
    "${HADOOP_DEST}/bin/hdfs" namenode -format -force

    # Load variables for the current running script session
    load_env

    echo -e "\n  ${GREEN}[✓] Installation completed successfully!${NC}"
    echo -e "      Please reload your shell profile to apply variables globally:"
    echo -e "      ${YELLOW}source ${SHELL_CONFIG}${NC}"
    send_notification "Hadoop Handler" "Hadoop installation and NameNode format finished."
}

# 2. Verify Hadoop Installation
verify_hadoop() {
    clear
    load_env
    echo -e "$DIVIDER"
    echo -e "  ${BCYAN}ACTION: Verifying Hadoop System Status${NC}"
    echo -e "$DIVIDER\n"
    
    if [ -z "$HADOOP_HOME" ] || [ ! -d "$HADOOP_HOME" ]; then
        echo -e "  ${RED}[!] Error: Hadoop is not installed or HADOOP_HOME is not set correctly.${NC}"
        return
    fi
    echo -e "  ${GRAY}HADOOP_HOME:${NC} ${GREEN}${HADOOP_HOME}${NC}"
    
    echo -ne "  ${GRAY}Hadoop binary:${NC} "
    if command -v hadoop >/dev/null 2>&1; then
        echo -e "${GREEN}Available${NC} ($(hadoop version | head -n 1))"
    else
        echo -e "${RED}Not found in PATH${NC} (Try sourcing shell profile)"
    fi

    echo -ne "  ${GRAY}Java version:${NC}  "
    if command -v java >/dev/null 2>&1; then
        echo -e "${GREEN}Available${NC} ($(java -version 2>&1 | head -n 1))"
    else
        echo -e "${RED}Not found${NC}"
    fi

    echo -e "\n  ${GRAY}Active Cluster Daemons (jps):${NC}"
    echo -e "  $DIVIDER"
    if command -v jps >/dev/null 2>&1; then
        jps | sed 's/^/  /'
    else
        echo -e "  ${RED}'jps' command is not available. Please ensure OpenJDK is fully configured.${NC}"
    fi
}

# 3. Start Hadoop Services
start_services() {
    clear
    load_env
    echo -e "$DIVIDER"
    echo -e "  ${BCYAN}ACTION: Starting Hadoop Services (HDFS & YARN)${NC}"
    echo -e "$DIVIDER\n"
    
    if [ -z "$HADOOP_HOME" ] || [ ! -d "$HADOOP_HOME" ]; then
        echo -e "  ${RED}[!] Error: Hadoop is not installed. Please run Option 1 first.${NC}"
        return
    fi

    # Start HDFS (NameNode, DataNode, SecondaryNameNode)
    echo -e "  ${GRAY}[1/2]${NC} Starting Distributed File System (HDFS)..."
    if command -v start-dfs.sh >/dev/null 2>&1; then
        start-dfs.sh
    else
        "${HADOOP_HOME}/sbin/start-dfs.sh"
    fi

    # Start YARN (ResourceManager, NodeManager)
    echo -e "\n  ${GRAY}[2/2]${NC} Starting YARN Resource Negotiator..."
    if command -v start-yarn.sh >/dev/null 2>&1; then
        start-yarn.sh
    else
        "${HADOOP_HOME}/sbin/start-yarn.sh"
    fi

    echo -e "\n  ${GREEN}[✓] Active Hadoop daemons after startup:${NC}"
    echo -e "  $DIVIDER"
    if command -v jps >/dev/null 2>&1; then
        jps | sed 's/^/  /'
    fi
    send_notification "Hadoop Handler" "Hadoop cluster services (HDFS & YARN) started."
}

# 4. Stop Hadoop Services
stop_services() {
    clear
    load_env
    echo -e "$DIVIDER"
    echo -e "  ${BCYAN}ACTION: Stopping Hadoop Services (YARN & HDFS)${NC}"
    echo -e "$DIVIDER\n"
    
    if [ -z "$HADOOP_HOME" ] || [ ! -d "$HADOOP_HOME" ]; then
        echo -e "  ${RED}[!] Error: Hadoop is not installed.${NC}"
        return
    fi

    # Stop YARN
    echo -e "  ${GRAY}[1/2]${NC} Stopping YARN Resource Manager & Nodes..."
    if command -v stop-yarn.sh >/dev/null 2>&1; then
        stop-yarn.sh
    else
        "${HADOOP_HOME}/sbin/stop-yarn.sh"
    fi

    # Stop HDFS
    echo -e "\n  ${GRAY}[2/2]${NC} Stopping Distributed File System (HDFS)..."
    if command -v stop-dfs.sh >/dev/null 2>&1; then
        stop-dfs.sh
    else
        "${HADOOP_HOME}/sbin/stop-dfs.sh"
    fi

    echo -e "\n  ${GREEN}[✓] Remaining active daemons:${NC}"
    echo -e "  $DIVIDER"
    if command -v jps >/dev/null 2>&1; then
        jps | sed 's/^/  /'
    fi
    send_notification "Hadoop Handler" "Hadoop cluster services stopped."
}

# 5. Delete Hadoop Completely
delete_hadoop() {
    clear
    echo -e "$DIVIDER"
    echo -e "  ${BRED}ACTION: Completely Uninstalling Hadoop${NC}"
    echo -e "$DIVIDER\n"
    
    echo -e "  ${RED}[!] WARNING: This will permanently delete your Hadoop installation,${NC}"
    echo -e "  ${RED}    configuration files, HDFS directories, and path profiles.${NC}\n"
    read -p "  Are you sure you want to proceed? (y/N): " confirm
    
    if [[ "$confirm" =~ ^[Yy]$ ]]; then
        load_env
        
        # Stop services first
        stop_services >/dev/null 2>&1 || true
        
        echo -e "\n  ${GRAY}[1/3]${NC} Deleting binaries and directories..."
        if [ -d "$HADOOP_HOME" ]; then
            if [ "$OS_NAME" = "Linux" ]; then
                sudo rm -rf "$HADOOP_HOME" /opt/hadoop_data /opt/hadoop_tmp
            else
                rm -rf "$HADOOP_HOME" ~/hadoopdata ~/hadooptmp /Users/Shared/hadoop /Users/Shared/hadoop_data /Users/Shared/hadoop_tmp
            fi
            echo -e "        Deleted ${HADOOP_HOME} and data directories."
        fi

        echo -e "\n  ${GRAY}[2/3]${NC} Removing downloaded archives..."
        rm -f "$HOME/Downloads/hadoop-3.4.2.tar.gz"
        echo -e "        Removed tarball cache."

        echo -e "\n  ${GRAY}[3/3]${NC} Cleaning up environment variables..."
        for profile in "$HOME/.bashrc" "$HOME/.zshrc"; do
            if [ -f "$profile" ]; then
                sed -i.bak '/# --- HADOOP HANDLER ENVIRONMENT VARIABLES ---/,/export PATH=.*HADOOP/d' "$profile" 2>/dev/null || \
                sed -i '' '/# --- HADOOP HANDLER ENVIRONMENT VARIABLES ---/,/export PATH=.*HADOOP/d' "$profile" 2>/dev/null
                rm -f "${profile}.bak"
                echo -e "        Cleaned environment variables from ${profile}."
            fi
        done

        # Reset session variables
        unset HADOOP_HOME
        unset HADOOP_CONF_DIR
        unset HADOOP_COMMON_HOME
        unset HADOOP_HDFS_HOME
        unset HADOOP_MAPRED_HOME
        unset YARN_HOME
        unset HADOOP_COMMON_LIB_NATIVE_DIR

        echo -e "\n  ${GREEN}[✓] Uninstall completed. Please reload your shell profile:${NC}"
        echo -e "      ${YELLOW}source ~/.bashrc${NC} (or ${YELLOW}source ~/.zshrc${NC})"
        send_notification "Hadoop Handler" "Hadoop installation uninstalled."
    else
        echo -e "  ${YELLOW}Uninstall aborted.${NC}"
    fi
}

# 6. System Service Integration (systemd / launchd)
manage_system_service() {
    local action="$1"
    
    if [ "$OS_NAME" = "Linux" ]; then
        local unit_dir="$HOME/.config/systemd/user"
        local unit_file="${unit_dir}/hadoop.service"
        local hadoop_bin="$(command -v hadoop-handler 2>/dev/null || echo "${SCRIPT_DIR}/hadoop-handler")"
        
        if [ -z "$action" ]; then
            clear
            echo -e "$DIVIDER"
            echo -e "  ${BCYAN}ACTION: System Service Integration (systemd)${NC}"
            echo -e "$DIVIDER"
            echo -e "  1. Enable Hadoop service on boot/login (systemd user unit)"
            echo -e "  2. Disable Hadoop service"
            echo -e "  3. View service status (systemctl --user status hadoop)"
            echo -e "  4. Start service via systemctl"
            echo -e "  5. Stop service via systemctl"
            echo -e "  6. Back to main menu"
            echo -e "$DIVIDER"
            read -p "  Select action [1-6]: " svc_choice
            case "$svc_choice" in
                1) action="enable" ;;
                2) action="disable" ;;
                3) action="status" ;;
                4) action="start" ;;
                5) action="stop" ;;
                *) return 0 ;;
            esac
        fi
        
        case "$action" in
            enable)
                echo -e "  [+] Generating user systemd unit: ${unit_file}..."
                mkdir -p "$unit_dir"
                cat << EOF > "$unit_file"
[Unit]
Description=Apache Hadoop Single-Node Services (HDFS & YARN)
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
Environment="HADOOP_HOME=${HADOOP_HOME:-/opt/hadoop}"
Environment="JAVA_HOME=${JAVA_HOME}"
ExecStart=${hadoop_bin} start
ExecStop=${hadoop_bin} stop

[Install]
WantedBy=default.target
EOF
                systemctl --user daemon-reload
                systemctl --user enable hadoop.service
                echo -e "  ${GREEN}[✓] Hadoop service enabled!${NC}"
                echo -e "      Hadoop services will now automatically launch on user login."
                send_notification "Hadoop Handler" "Hadoop systemd user service enabled."
                ;;
            disable)
                echo -e "  [+] Disabling Hadoop systemd service..."
                systemctl --user stop hadoop.service 2>/dev/null || true
                systemctl --user disable hadoop.service 2>/dev/null || true
                rm -f "$unit_file"
                systemctl --user daemon-reload
                echo -e "  ${GREEN}[✓] Hadoop systemd service disabled and unit removed.${NC}"
                send_notification "Hadoop Handler" "Hadoop systemd service disabled."
                ;;
            status)
                systemctl --user status hadoop.service --no-pager
                ;;
            start)
                echo -e "  [+] Starting hadoop.service via systemctl..."
                systemctl --user start hadoop.service
                echo -e "  ${GREEN}[✓] Signal dispatched to systemd.${NC}"
                ;;
            stop)
                echo -e "  [+] Stopping hadoop.service via systemctl..."
                systemctl --user stop hadoop.service
                echo -e "  ${GREEN}[✓] Signal dispatched to systemd.${NC}"
                ;;
            *)
                echo -e "  ${RED}[!] Unknown service action: ${action}${NC}"
                echo -e "      Supported: enable, disable, status, start, stop"
                ;;
        esac
    elif [ "$OS_NAME" = "Darwin" ]; then
        local plist_dir="$HOME/Library/LaunchAgents"
        local plist_file="${plist_dir}/in.adityapidurkar.hadoop.plist"
        local hadoop_bin="$(command -v hadoop-handler 2>/dev/null || echo "${SCRIPT_DIR}/hadoop-handler")"

        case "$action" in
            enable)
                mkdir -p "$plist_dir"
                cat << EOF > "$plist_file"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>in.adityapidurkar.hadoop</string>
    <key>ProgramArguments</key>
    <array>
        <string>${hadoop_bin}</string>
        <string>start</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF
                launchctl load "$plist_file" 2>/dev/null || true
                echo -e "  ${GREEN}[✓] LaunchAgent enabled for macOS.${NC}"
                send_notification "Hadoop Handler" "Hadoop LaunchAgent service enabled."
                ;;
            disable)
                launchctl unload "$plist_file" 2>/dev/null || true
                rm -f "$plist_file"
                echo -e "  ${GREEN}[✓] LaunchAgent disabled for macOS.${NC}"
                ;;
            *)
                echo -e "  ${YELLOW}Use 'hadoop-handler service enable' or 'disable' on macOS.${NC}"
                ;;
        esac
    fi
}

# 7. Check for Updates and Perform In-Place Self-Update
self_update() {
    clear
    echo -e "$DIVIDER"
    echo -e "  ${BCYAN}ACTION: Checking & Updating Hadoop Handler${NC}"
    echo -e "$DIVIDER\n"

    local updated=false

    # 1. Update ~/.hadoop-handler if present
    if [ -d "$HOME/.hadoop-handler/.git" ]; then
        echo -e "  [+] Checking global installation in ~/.hadoop-handler..."
        (cd "$HOME/.hadoop-handler" && git pull origin main)
        chmod +x "$HOME/.hadoop-handler/hadoop-handler" "$HOME/.hadoop-handler/setup.sh" 2>/dev/null || true
        updated=true
    fi

    # 2. Update local repository if different
    if [ -d "${SCRIPT_DIR}/.git" ] && [ "${SCRIPT_DIR}" != "$HOME/.hadoop-handler" ]; then
        echo -e "  [+] Pulling latest changes in ${SCRIPT_DIR}..."
        (cd "${SCRIPT_DIR}" && git pull origin main)
        chmod +x "${SCRIPT_DIR}/hadoop-handler" 2>/dev/null || true
        updated=true
    fi

    # 3. Update pip package if installed via pip
    if command -v pip >/dev/null 2>&1 && pip list 2>/dev/null | grep -q "hadoop-handler"; then
        echo -e "  [+] Upgrading pip package..."
        pip install --upgrade hadoop-handler 2>/dev/null || true
        updated=true
    elif command -v python3 >/dev/null 2>&1 && python3 -m pip list 2>/dev/null | grep -q "hadoop-handler"; then
        echo -e "  [+] Upgrading python3 pip package..."
        python3 -m pip install --upgrade hadoop-handler 2>/dev/null || true
        updated=true
    fi

    rm -f "$HOME/.hadoop-handler/.version_cache" 2>/dev/null || true

    if [ "$updated" = "true" ]; then
        echo -e "\n  ${GREEN}[✓] Hadoop Handler is up to date!${NC}"
        send_notification "Hadoop Handler" "Hadoop Handler updated to the latest version."
    else
        echo -e "\n  ${YELLOW}[*] No git or pip package found to update.${NC}"
    fi
}

# 8. Shell Autocompletion
install_shell_completion() {
    local target_shell="$1"
    if [ -z "$target_shell" ]; then
        target_shell="$(basename "$SHELL")"
    fi

    clear
    echo -e "$DIVIDER"
    echo -e "  ${BCYAN}ACTION: Installing Shell Autocompletion (${target_shell})${NC}"
    echo -e "$DIVIDER\n"

    case "$target_shell" in
        bash)
            local rc_file="$HOME/.bashrc"
            if ! grep -q "_hadoop_handler_completions" "$rc_file" 2>/dev/null; then
                cat << "EOF" >> "$rc_file"

# Hadoop Handler shell completion
_hadoop_handler_completions() {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="diagnose install verify status start stop restart delete service update completion --version --help --install-completion"

    if [ "$prev" = "service" ]; then
        COMPREPLY=( $(compgen -W "enable disable status start stop" -- "$cur") )
        return 0
    elif [ "$prev" = "completion" ]; then
        COMPREPLY=( $(compgen -W "bash zsh fish powershell" -- "$cur") )
        return 0
    fi

    COMPREPLY=( $(compgen -W "${opts}" -- "$cur") )
    return 0
}
complete -F _hadoop_handler_completions hadoop-handler
EOF
                echo -e "  ${GREEN}[✓] Bash completions added to ${rc_file}!${NC}"
                echo -e "      To activate immediately, run: ${YELLOW}source ${rc_file}${NC}"
            else
                echo -e "  ${YELLOW}[*] Completions already registered in ${rc_file}.${NC}"
            fi
            ;;
        zsh)
            local rc_file="$HOME/.zshrc"
            if ! grep -q "_hadoop_handler_completions" "$rc_file" 2>/dev/null; then
                cat << "EOF" >> "$rc_file"

# Hadoop Handler shell completion
autoload -Uz bashcompinit && bashcompinit
_hadoop_handler_completions() {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="diagnose install verify status start stop restart delete service update completion --version --help --install-completion"

    if [ "$prev" = "service" ]; then
        COMPREPLY=( $(compgen -W "enable disable status start stop" -- "$cur") )
        return 0
    elif [ "$prev" = "completion" ]; then
        COMPREPLY=( $(compgen -W "bash zsh fish powershell" -- "$cur") )
        return 0
    fi

    COMPREPLY=( $(compgen -W "${opts}" -- "$cur") )
    return 0
}
complete -F _hadoop_handler_completions hadoop-handler
EOF
                echo -e "  ${GREEN}[✓] Zsh completions added to ${rc_file}!${NC}"
                echo -e "      To activate immediately, run: ${YELLOW}source ${rc_file}${NC}"
            else
                echo -e "  ${YELLOW}[*] Completions already registered in ${rc_file}.${NC}"
            fi
            ;;
        fish)
            local fish_dir="$HOME/.config/fish/completions"
            mkdir -p "$fish_dir"
            cat << "EOF" > "${fish_dir}/hadoop-handler.fish"
complete -c hadoop-handler -f -a "diagnose install verify status start stop restart delete service update completion --version --help --install-completion"
complete -c hadoop-handler -n "__fish_seen_subcommand_from service" -f -a "enable disable status start stop"
complete -c hadoop-handler -n "__fish_seen_subcommand_from completion" -f -a "bash zsh fish powershell"
EOF
            echo -e "  ${GREEN}[✓] Fish completions saved to ${fish_dir}/hadoop-handler.fish!${NC}"
            ;;
        powershell)
            cat << "EOF"
Register-ArgumentCompleter -Native -CommandName hadoop-handler -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)
    $commands = @('diagnose', 'install', 'verify', 'status', 'start', 'stop', 'restart', 'delete', 'service', 'update', 'completion', '--version', '--help')
    $commands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
        [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
    }
}
EOF
            echo -e "  ${GREEN}[✓] Add the snippet above to your PowerShell profile (\$PROFILE).${NC}"
            ;;
        *)
            echo -e "  ${RED}[!] Unsupported shell: ${target_shell}. Supported: bash, zsh, fish, powershell.${NC}"
            ;;
    esac
}

# 0. Diagnose Environment
diagnose_environment() {
    clear
    echo -e "$DIVIDER"
    echo -e "  ${BCYAN}ACTION: Diagnosing System Dependencies${NC}"
    echo -e "$DIVIDER\n"
    
    local missing_deps=()
    local repair_cmds=()
    
    echo -e "  ${GRAY}Scanning critical utilities...${NC}"
    
    # 1. Package Manager Detection
    local pkg_manager=""
    if [ "$OS_NAME" = "Linux" ]; then
        if command -v apt-get >/dev/null 2>&1; then
            pkg_manager="apt"
        elif command -v dnf >/dev/null 2>&1; then
            pkg_manager="dnf"
        elif command -v yum >/dev/null 2>&1; then
            pkg_manager="yum"
        elif command -v pacman >/dev/null 2>&1; then
            pkg_manager="pacman"
        elif command -v zypper >/dev/null 2>&1; then
            pkg_manager="zypper"
        fi
    elif [ "$OS_NAME" = "Darwin" ]; then
        if command -v brew >/dev/null 2>&1; then
            pkg_manager="brew"
        fi
    fi

    # Helper function to check command and suggest repair
    check_dependency() {
        local cmd=$1
        local pkg_apt=$2
        local pkg_dnf=$3
        local pkg_pacman=$4
        local pkg_brew=$5

        echo -ne "  - Checking for ${CYAN}${cmd}${NC}... "
        if command -v "$cmd" >/dev/null 2>&1; then
            echo -e "${GREEN}[OK]${NC}"
        else
            echo -e "${RED}[MISSING]${NC}"
            missing_deps+=("$cmd")
            
            case "$pkg_manager" in
                apt)
                    [ -n "$pkg_apt" ] && repair_cmds+=("sudo apt-get install -y $pkg_apt")
                    ;;
                dnf|yum)
                    [ -n "$pkg_dnf" ] && repair_cmds+=("sudo $pkg_manager install -y $pkg_dnf")
                    ;;
                pacman)
                    [ -n "$pkg_pacman" ] && repair_cmds+=("sudo pacman -S --noconfirm $pkg_pacman")
                    ;;
                brew)
                    [ -n "$pkg_brew" ] && repair_cmds+=("brew install $pkg_brew")
                    ;;
            esac
        fi
    }

    # Core utilities required by Hadoop scripts
    check_dependency "curl" "curl" "curl" "curl" "curl"
    check_dependency "tar" "tar" "tar" "tar" ""
    check_dependency "ssh" "openssh-client openssh-server" "openssh-clients openssh-server" "openssh" ""
    check_dependency "rsync" "rsync" "rsync" "rsync" "rsync"
    
    # Check Java
    echo -ne "  - Checking for ${CYAN}Java (OpenJDK 21)${NC}... "
    if command -v java >/dev/null 2>&1; then
        local jv=$(java -version 2>&1 | head -n 1 | awk -F '"' '{print $2}')
        if [[ "$jv" == 21* ]]; then
            echo -e "${GREEN}[OK] (${jv})${NC}"
        else
            echo -e "${YELLOW}[VERSION MISMATCH] (Found ${jv}, required 21)${NC}"
            missing_deps+=("java21")
            case "$pkg_manager" in
                apt) repair_cmds+=("sudo apt-get install -y openjdk-21-jdk") ;;
                dnf|yum) repair_cmds+=("sudo $pkg_manager install -y java-21-openjdk-devel") ;;
                pacman) repair_cmds+=("sudo pacman -S --noconfirm jre21-openjdk jdk21-openjdk") ;;
                brew) repair_cmds+=("brew install openjdk@21") ;;
            esac
        fi
    else
        echo -e "${RED}[MISSING]${NC}"
        missing_deps+=("java21")
        case "$pkg_manager" in
            apt) repair_cmds+=("sudo apt-get install -y openjdk-21-jdk") ;;
            dnf|yum) repair_cmds+=("sudo $pkg_manager install -y java-21-openjdk-devel") ;;
            pacman) repair_cmds+=("sudo pacman -S --noconfirm jre21-openjdk jdk21-openjdk") ;;
            brew) repair_cmds+=("brew install openjdk@21") ;;
        esac
    fi

    # SSH Server Status (Linux only)
    if [ "$OS_NAME" = "Linux" ]; then
        echo -ne "  - Checking for ${CYAN}SSH Daemon (sshd)${NC}... "
        if systemctl is-active --quiet ssh 2>/dev/null || systemctl is-active --quiet sshd 2>/dev/null; then
            echo -e "${GREEN}[RUNNING]${NC}"
        else
            echo -e "${YELLOW}[NOT RUNNING]${NC}"
            missing_deps+=("sshd_service")
            repair_cmds+=("sudo systemctl enable --now ssh 2>/dev/null || sudo systemctl enable --now sshd")
        fi
    fi

    echo -e "\n$DIVIDER"
    if [ ${#missing_deps[@]} -eq 0 ]; then
        echo -e "  ${GREEN}[✓] System scan complete! All dependencies are satisfied.${NC}"
        rm -f /tmp/hadoop_repair_cmds.txt /tmp/hadoop_repair_missing.txt
        return 0
    else
        echo -e "  ${YELLOW}[!] Diagnostics identified ${#missing_deps[@]} missing requirement(s).${NC}"
        
        # Save repair commands to temp files
        printf "%s\n" "${repair_cmds[@]}" > /tmp/hadoop_repair_cmds.txt
        printf "%s\n" "${missing_deps[@]}" > /tmp/hadoop_repair_missing.txt
        return 1
    fi
}

apply_repairs() {
    local dry_run=$1
    if [ ! -f /tmp/hadoop_repair_cmds.txt ]; then
        echo -e "  ${YELLOW}No pending repairs found. Please run Diagnostics first.${NC}"
        return 0
    fi
    
    if [ "$dry_run" = "true" ]; then
        echo -e "\n  ${BCYAN}--- DRY RUN MODE ---${NC}"
        echo -e "  The following commands would be executed:"
        while read -r cmd; do
            echo -e "  > $cmd"
        done < /tmp/hadoop_repair_cmds.txt
        return 0
    fi

    echo -e "\n  ${BCYAN}ACTION: Applying Repairs${NC}"
    echo -e "  $DIVIDER"
    
    while read -r cmd; do
        echo -e "  ${GRAY}Executing: $cmd${NC}"
        eval "$cmd"
        if [ $? -ne 0 ]; then
            echo -e "  ${RED}[!] Repair step failed: $cmd${NC}"
            echo -e "  ${YELLOW}Aborting further repairs.${NC}"
            rm -f /tmp/hadoop_repair_cmds.txt /tmp/hadoop_repair_missing.txt
            return 1
        fi
    done < /tmp/hadoop_repair_cmds.txt
    
    echo -e "  ${GREEN}[✓] All repairs completed successfully!${NC}"
    rm -f /tmp/hadoop_repair_cmds.txt /tmp/hadoop_repair_missing.txt
    send_notification "Hadoop Handler" "System dependency repairs finished."
}

diagnose_and_repair() {
    diagnose_environment
    if [ -f /tmp/hadoop_repair_cmds.txt ]; then
        echo -e "\n  Do you want to apply these repairs now? (y/N/dryrun)"
        read -p "  > " confirm
        if [[ "$confirm" =~ ^[Yy]$ ]]; then
            apply_repairs "false"
        elif [[ "$confirm" == "dryrun" ]]; then
            apply_repairs "true"
        else
            echo -e "  ${YELLOW}Repairs cancelled.${NC}"
        fi
    fi
}

# Banner and Visual Status Badges
show_banner_and_status() {
    echo -e "${CYAN}"
    cat << "EOF"
█ █  ███  ██   ███  ███  ███    █ █  ███  ██ █  ██   █    ███  ███
███  █ █  █ █  █ █  █ █  ███    ███  █ █  █ ██  █ █  █    ██   ███
█ █  █ █  ██   ███  ███  █      █ █  █ █  █  █  ██   ███  ███  █ █
EOF
    echo -e "${NC}"
    echo -e "  ${GRAY}Developer:${NC} ${BCYAN}Aditya Pidurkar${NC} (${CYAN}github.com/itsadityapidurkar${NC})"
    echo -e "  ${GRAY}Scope:${NC}     Apache Hadoop 3.4.2 Single-Node Control Center"
    echo -e "$DIVIDER"
    
    # Check for update banner
    check_version_banner

    # Compute status badges
    local h_stat=""
    if command -v hadoop >/dev/null 2>&1; then
        local h_ver=$(hadoop version 2>/dev/null | head -n 1 | awk '{print $2}')
        [ -z "$h_ver" ] && h_ver="3.4.2"
        h_stat="${BGREEN}[✓ Installed (${h_ver})]${NC}"
    elif [ -n "$HADOOP_HOME" ] && [ -d "$HADOOP_HOME" ]; then
        h_stat="${BGREEN}[✓ Installed]${NC}"
    else
        h_stat="${BRED}[✗ Not Installed]${NC}"
    fi

    local j_stat=""
    if command -v java >/dev/null 2>&1; then
        local j_ver=$(java -version 2>&1 | head -n 1 | sed -E 's/.*version "([^"]+)".*/\1/' | cut -d'.' -f1)
        [ "$j_ver" = "1" ] && j_ver="8"
        j_stat="${BGREEN}[✓ OpenJDK ${j_ver}]${NC}"
    else
        j_stat="${BRED}[✗ Missing]${NC}"
    fi

    local s_stat=""
    local d_count=0
    if command -v jps >/dev/null 2>&1; then
        for d in NameNode DataNode SecondaryNameNode ResourceManager NodeManager; do
            if jps 2>/dev/null | grep -wq "$d"; then
                ((d_count++))
            fi
        done
    fi

    if [ $d_count -eq 5 ]; then
        s_stat="${BGREEN}[✓ 5/5 Daemons Running]${NC}"
    elif [ $d_count -gt 0 ]; then
        s_stat="${YELLOW}[● ${d_count}/5 Daemons Running]${NC}"
    else
        s_stat="${GRAY}[● Stopped]${NC}"
    fi

    echo -e "  ${GRAY}Cluster Status:${NC}"
    echo -e "    Hadoop:   ${h_stat}"
    echo -e "    Java:     ${j_stat}"
    echo -e "    Services: ${s_stat}"
}

MENU_OPTIONS=(
    "Diagnose/Repair System Dependencies"
    "Install Hadoop"
    "Verify Hadoop Installation"
    "Start Hadoop Services (HDFS & YARN)"
    "Stop Hadoop Services"
    "Delete Hadoop Completely"
    "System Service Integration (systemd)"
    "Check for Updates (Self-Update)"
    "Install Shell Autocompletion"
    "Exit"
)

MENU_CHOICE=""

render_options() {
    local selected="$1"
    local num_options=${#MENU_OPTIONS[@]}
    for i in "${!MENU_OPTIONS[@]}"; do
        if [ "$i" -eq "$selected" ]; then
            printf "\033[2K  %b▶%b %b[ %d ] %s%b\n" "$BCYAN" "$NC" "$BGREEN" "$i" "${MENU_OPTIONS[$i]}" "$NC"
        else
            printf "\033[2K    %b[ %d ]%b %s\n" "$GRAY" "$i" "$NC" "${MENU_OPTIONS[$i]}"
        fi
    done
    printf "\033[2K%b\n" "$DIVIDER"
    printf "\033[2K  %bUse [↑/↓] (or j/k) and [Enter] to select, or press [0-%d] directly%b\n" "$GRAY" "$((num_options - 1))" "$NC"
}

# Arrow-Key Navigation Menu Selector (Zero Flicker)
select_menu_option() {
    MENU_CHOICE=""
    local selected=0
    local key=""
    local num_options=${#MENU_OPTIONS[@]}
    local lines_count=$((num_options + 2))

    # Fallback to plain prompt if stdin is not a TTY (for piping/scripting)
    if [ ! -t 0 ]; then
        clear
        show_banner_and_status
        echo -e "$DIVIDER"
        for i in "${!MENU_OPTIONS[@]}"; do
            echo -e "  [ $i ] ${MENU_OPTIONS[$i]}"
        done
        echo -e "$DIVIDER"
        read -r choice || choice=9
        MENU_CHOICE="${choice:-9}"
        return 0
    fi

    # Clear once at start of menu session
    clear
    show_banner_and_status
    echo -e "$DIVIDER"

    # Hide cursor
    tput civis 2>/dev/null || printf "\033[?25l"
    trap 'tput cnorm 2>/dev/null || printf "\033[?25h"' RETURN EXIT INT TERM

    # Initial render of options
    render_options "$selected"

    while true; do
        IFS= read -rsn1 key
        local old_selected=$selected

        if [ "$key" = $'\x1b' ]; then
            read -rsn2 -t 0.1 rest
            key+="$rest"
            case "$key" in
                $'\x1b[A'|$'\x1bOA') # Up arrow
                    ((selected--))
                    [ $selected -lt 0 ] && selected=$((num_options - 1))
                    ;;
                $'\x1b[B'|$'\x1bOB') # Down arrow
                    ((selected++))
                    [ $selected -ge $num_options ] && selected=0
                    ;;
            esac
        elif [ "$key" = "k" ] || [ "$key" = "K" ]; then
            ((selected--))
            [ $selected -lt 0 ] && selected=$((num_options - 1))
        elif [ "$key" = "j" ] || [ "$key" = "J" ]; then
            ((selected++))
            [ $selected -ge $num_options ] && selected=0
        elif [ -z "$key" ] || [ "$key" = $'\n' ]; then
            break
        elif [[ "$key" =~ ^[0-9]$ ]] && [ "$key" -lt "$num_options" ]; then
            selected="$key"
            break
        elif [ "$key" = "q" ] || [ "$key" = "Q" ]; then
            selected=$((num_options - 1))
            break
        fi

        # In-place redraw without screen clearing (smooth, zero-flicker)
        if [ "$selected" -ne "$old_selected" ]; then
            printf "\033[%dA" "$lines_count"
            render_options "$selected"
        fi
    done

    # Restore cursor
    tput cnorm 2>/dev/null || printf "\033[?25h"
    MENU_CHOICE="$selected"
}

# Load environment on launch
load_env

# CLI Subcommands & Flags
if [ -n "$1" ]; then
    case "$1" in
        0|diagnose|repair)
            diagnose_and_repair
            exit $?
            ;;
        1|install)
            install_hadoop
            exit $?
            ;;
        2|verify|status)
            verify_hadoop
            exit $?
            ;;
        3|start)
            start_services
            exit $?
            ;;
        4|stop)
            stop_services
            exit $?
            ;;
        restart)
            stop_services
            sleep 2
            start_services
            exit $?
            ;;
        5|delete)
            delete_hadoop
            exit $?
            ;;
        6|service)
            shift
            manage_system_service "$@"
            exit $?
            ;;
        7|update|self-update)
            self_update
            exit $?
            ;;
        8|completion)
            shift
            install_shell_completion "$@"
            exit $?
            ;;
        --install-completion)
            install_shell_completion
            exit $?
            ;;
        menu)
            # Fall through to interactive loop
            ;;
        -v|--version)
            echo "hadoop-handler ${CURRENT_VERSION}"
            exit 0
            ;;
        -h|--help)
            echo "Hadoop Handler v${CURRENT_VERSION} — Single-Node Cluster Control Center"
            echo "Usage: hadoop-handler [command] [options]"
            echo ""
            echo "Commands:"
            echo "  (no args)               Launch interactive TUI control panel"
            echo "  diagnose                Diagnose/Repair system dependencies"
            echo "  install                 Install and configure Apache Hadoop 3.4.2"
            echo "  verify, status          Check Hadoop and Java status and running daemons"
            echo "  start                   Start Hadoop services (HDFS & YARN)"
            echo "  stop                    Stop Hadoop services"
            echo "  restart                 Restart all cluster daemons"
            echo "  delete                  Delete Hadoop cluster installation completely"
            echo "  service <action>        Manage system service (enable|disable|status|start|stop)"
            echo "  update                  Check and perform in-place self-update"
            echo "  completion <shell>      Generate autocompletion script (bash|zsh|fish|powershell)"
            echo "  --install-completion    Automatically install autocompletion for current shell"
            echo "  -v, --version           Show version"
            echo "  -h, --help              Show this help message"
            exit 0
            ;;
        *)
            echo "Unknown command: $1"
            echo "Run 'hadoop-handler --help' for usage."
            exit 1
            ;;
    esac
fi

# Interactive Menu Loop
while true; do
    select_menu_option
    
    case $MENU_CHOICE in
        0)
            diagnose_and_repair
            pause_screen
            ;;
        1)
            install_hadoop
            pause_screen
            ;;
        2)
            verify_hadoop
            pause_screen
            ;;
        3)
            start_services
            pause_screen
            ;;
        4)
            stop_services
            pause_screen
            ;;
        5)
            delete_hadoop
            pause_screen
            ;;
        6)
            manage_system_service
            pause_screen
            ;;
        7)
            self_update
            pause_screen
            ;;
        8)
            install_shell_completion
            pause_screen
            ;;
        9)
            clear
            echo -e "\n  Exiting Hadoop Handler. Goodbye!"
            exit 0
            ;;
        *)
            echo -e "  ${RED}[!] Invalid choice.${NC}"
            sleep 1.2
            ;;
    esac
done
