#!/bin/bash

################################################################################
# Malware Scanner
################################################################################
# Purpose: Comprehensive malware scanning with multiple engines
# Supports: ImunifyAV, ClamAV, Maldet (LMD)
# Scan scope: Single domain, user account, or entire server
################################################################################

set -eo pipefail

# Color definitions (matching launcher.sh)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"

# Source required libraries (warn if missing, but allow graceful degradation)
source "$SCRIPT_DIR/lib/common-functions.sh" 2>/dev/null || \
    { echo "WARNING: common-functions.sh not found - some features may not work" >&2; }
source "$SCRIPT_DIR/lib/system-detect.sh" 2>/dev/null || \
    { echo "WARNING: system-detect.sh not found - control panel detection may fail" >&2; }
source "$SCRIPT_DIR/lib/user-manager.sh" 2>/dev/null || \
    { echo "WARNING: user-manager.sh not found - user selection may not work" >&2; }
source "$SCRIPT_DIR/lib/reference-db.sh" 2>/dev/null || true  # Optional
source "$SCRIPT_DIR/lib/ip-reputation.sh" 2>/dev/null || true  # Optional

# Arrays for docroots and scanners
declare -a docroot_array
declare -a sanitized_docroot
declare -a remove_docroot
declare -a available_scanners

# Validate that required functions were sourced from libraries
# These functions must exist for the script to work properly
validate_required_functions() {
    local required_functions=(
        "confirm"
        "print_header"
        "print_banner"
        "select_user_interactive"
        "get_user_domains"
    )

    for func in "${required_functions[@]}"; do
        if ! declare -f "$func" &>/dev/null; then
            echo "ERROR: Required function '$func' not found." >&2
            echo "       Check that library files exist in: $SCRIPT_DIR/lib/" >&2
            return 1
        fi
    done

    return 0
}

# Validate functions early
if ! validate_required_functions; then
    exit 1
fi

# Auto-detect web server document root for ImunifyAV standalone UI path
get_web_root_for_imunify() {
    local detected_root=""

    # Try Apache on Debian/Ubuntu (apache2ctl)
    if command -v apache2ctl &>/dev/null; then
        detected_root=$(apache2ctl -S 2>/dev/null | grep "^\*:" | head -1 | awk '{print $NF}' | sed 's/*://' || echo "")
        if [ -n "$detected_root" ] && [ -d "$detected_root" ]; then
            echo "$detected_root"
            return 0
        fi
    fi

    # Try Apache on RHEL/CentOS (httpd -S)
    if command -v httpd &>/dev/null; then
        detected_root=$(httpd -S 2>/dev/null | grep "^\*:" | head -1 | awk '{print $NF}' | sed 's/*://' || echo "")
        if [ -n "$detected_root" ] && [ -d "$detected_root" ]; then
            echo "$detected_root"
            return 0
        fi
    fi

    # Try Nginx (nginx -T)
    if command -v nginx &>/dev/null; then
        detected_root=$(nginx -T 2>/dev/null | grep "^\s*root " | head -1 | awk '{print $NF}' | sed 's/;//' || echo "")
        if [ -n "$detected_root" ] && [ -d "$detected_root" ]; then
            echo "$detected_root"
            return 0
        fi
    fi

    # Try parsing Apache config files directly
    for conf_file in /etc/apache2/apache2.conf /etc/httpd/conf/httpd.conf /etc/apache2/sites-enabled/*.conf /etc/httpd/conf.d/*.conf; do
        if [ -f "$conf_file" ] 2>/dev/null; then
            detected_root=$(grep -E "^\s*DocumentRoot|^\s*root " "$conf_file" 2>/dev/null | head -1 | awk '{print $NF}' | sed 's/"//g' || echo "")
            if [ -n "$detected_root" ] && [ -d "$detected_root" ]; then
                echo "$detected_root"
                return 0
            fi
        fi
    done

    # Try Nginx config files directly
    for conf_file in /etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf /etc/nginx/sites-enabled/*.conf; do
        if [ -f "$conf_file" ] 2>/dev/null; then
            detected_root=$(grep -E "^\s*root " "$conf_file" 2>/dev/null | head -1 | awk '{print $NF}' | sed 's/;//' || echo "")
            if [ -n "$detected_root" ] && [ -d "$detected_root" ]; then
                echo "$detected_root"
                return 0
            fi
        fi
    done

    # Try common default locations in order of likelihood
    for path in /var/www/html /home /srv/www /var/www /usr/share/nginx/html /var/www/vhosts; do
        if [ -d "$path" ] && [ -w "$path" ]; then
            echo "$path"
            return 0
        fi
    done

    # Absolute fallback
    echo "/var/www/html"
}

# Individual scanner detection functions
is_imunify_installed() {
    command -v imunify-antivirus &>/dev/null || [ -f "/usr/bin/imunify-antivirus" ]
}

is_clamav_installed() {
    command -v clamscan &>/dev/null || \
    [ -f "/usr/local/cpanel/3rdparty/bin/clamscan" ] || \
    (command -v rpm &>/dev/null && rpm -qa 2>/dev/null | grep -q "cpanel-clamav" || true) || \
    (command -v dpkg &>/dev/null && dpkg -l 2>/dev/null | grep -q "^ii.*clamav" || true)
}

is_maldet_installed() {
    command -v maldet &>/dev/null || [ -f "/usr/local/sbin/maldet" ]
}

is_rkhunter_installed() {
    command -v rkhunter &>/dev/null || [ -f "/usr/bin/rkhunter" ]
}

# Cache scanner detection results (prevents redundant checks)
SCANNER_CACHE_INITIALIZED=false
IMUNIFY_INSTALLED_CACHE=false
CLAMAV_INSTALLED_CACHE=false
MALDET_INSTALLED_CACHE=false
RKHUNTER_INSTALLED_CACHE=false

cache_scanner_detection() {
    if [ "$SCANNER_CACHE_INITIALIZED" = true ]; then
        return 0  # Already cached
    fi

    IMUNIFY_INSTALLED_CACHE=$(is_imunify_installed && echo "true" || echo "false")
    CLAMAV_INSTALLED_CACHE=$(is_clamav_installed && echo "true" || echo "false")
    MALDET_INSTALLED_CACHE=$(is_maldet_installed && echo "true" || echo "false")
    RKHUNTER_INSTALLED_CACHE=$(is_rkhunter_installed && echo "true" || echo "false")
    SCANNER_CACHE_INITIALIZED=true
}

# Check cached scanner status (uses cache if available, falls back to direct check)
is_scanner_cached() {
    local scanner="$1"

    if [ "$SCANNER_CACHE_INITIALIZED" = true ]; then
        case "$scanner" in
            imunify) [ "$IMUNIFY_INSTALLED_CACHE" = "true" ] ;;
            clamav) [ "$CLAMAV_INSTALLED_CACHE" = "true" ] ;;
            maldet) [ "$MALDET_INSTALLED_CACHE" = "true" ] ;;
            rkhunter) [ "$RKHUNTER_INSTALLED_CACHE" = "true" ] ;;
            *) return 1 ;;
        esac
    else
        # Fall back to direct check if cache not initialized
        case "$scanner" in
            imunify) is_imunify_installed ;;
            clamav) is_clamav_installed ;;
            maldet) is_maldet_installed ;;
            rkhunter) is_rkhunter_installed ;;
            *) return 1 ;;
        esac
    fi
}

# Scanner detection
detect_scanners() {
    available_scanners=()

    if is_imunify_installed; then
        available_scanners+=("imunify")
    fi

    if is_clamav_installed; then
        available_scanners+=("clamav")
    fi

    if is_maldet_installed; then
        available_scanners+=("maldet")
    fi

    if is_rkhunter_installed; then
        available_scanners+=("rkhunter")
    fi

    # Note: If no scanners are found, available_scanners array will be empty
    # Menu option 9 allows installation, so we don't exit here
    # Just return success to allow menu to display
    return 0
}

# Show installation instructions for missing scanners (DEPRECATED - menu always shows now)
show_scanner_installation_guide() {
    echo -e "${YELLOW}Available Malware Scanners:${NC}"
    echo ""

    # Check ImunifyAV
    if ! is_imunify_installed; then
        echo -e "${CYAN}ImunifyAV${NC} - FREE real-time malware scanner"
        echo "  Status: Not installed"
        echo "  Installation (cPanel):"
        echo "    yum install imunify-antivirus imunify-antivirus-cpanel"
        echo "    /opt/alt/python35/share/imunify360/scripts/av-userside-plugin.sh"
        echo "  Installation (script method):"
        echo "    wget https://repo.imunify360.cloudlinux.com/defence360/imav-deploy.sh"
        echo "    bash imav-deploy.sh"
        echo "  Note: ImunifyAV is FREE. Imunify360 is the paid version."
        echo "  Docs: https://docs.imunify360.com/imunifyav/"
        echo ""
    else
        echo -e "${GREEN}✓ ImunifyAV${NC} - Installed (FREE version)"
        echo ""
    fi

    # Check ClamAV
    if ! is_clamav_installed; then
        echo -e "${CYAN}ClamAV${NC} - Open source antivirus engine"
        echo "  Status: Not installed"
        echo "  Installation (cPanel):"
        echo "    /scripts/update_local_rpm_versions --edit target_settings.clamav installed"
        echo "    /scripts/check_cpanel_rpms --fix --targets=clamav"
        echo "  Installation (manual):"
        echo "    yum install clamav clamav-update  # RHEL/CentOS"
        echo "    apt-get install clamav clamav-daemon  # Debian/Ubuntu"
        echo "    freshclam  # Update virus definitions"
        echo ""
    else
        echo -e "${GREEN}✓ ClamAV${NC} - Installed"
        echo ""
    fi

    # Check Maldet
    if ! is_maldet_installed; then
        echo -e "${CYAN}Maldet (LMD)${NC} - Linux Malware Detect"
        echo "  Status: Not installed"
        echo "  Installation:"
        echo "    cd /tmp"
        echo "    wget http://www.rfxn.com/downloads/maldetect-current.tar.gz"
        echo "    tar -xzf maldetect-current.tar.gz"
        echo "    cd maldetect-*"
        echo "    ./install.sh"
        echo "  Docs: https://www.rfxn.com/projects/linux-malware-detect/"
        echo ""
    else
        echo -e "${GREEN}✓ Maldet${NC} - Installed"
        echo ""
    fi

    # Check Rootkit Hunter
    if ! is_rkhunter_installed; then
        echo -e "${CYAN}Rootkit Hunter${NC} - Rootkit/backdoor/exploit scanner"
        echo "  Status: Not installed"
        echo "  Installation:"
        echo "    yum install epel-release -y  # Enable EPEL repo"
        echo "    yum install rkhunter -y"
        echo "    rkhunter --update  # Update definitions"
        echo "    rkhunter --propupd  # Initialize baseline"
        echo "  Docs: https://rkhunter.sourceforge.net/"
        echo ""
    else
        echo -e "${GREEN}✓ Rootkit Hunter${NC} - Installed"
        echo ""
    fi

    echo -e "${YELLOW}Recommendation:${NC} Install at least ClamAV + RKHunter (both free) for comprehensive protection"
    echo ""
}

# Install individual scanners
install_maldet_only() {
    echo ""
    print_header "Installing Maldet (Linux Malware Detection)"
    echo ""

    if is_maldet_installed; then
        echo -e "${GREEN}✓ Maldet is already installed${NC}"
        echo ""
        read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
        return 0
    fi

    echo "Maldet is a fast, Linux-specific malware scanner"
    echo "Repository: https://github.com/rfxn/maldet"
    echo ""
    echo "Checking available versions..."
    echo ""

    cd /tmp || return 1

    # Try to download from sources in order with aggressive timeout handling
    # Skip pre-checking (can hang on firewall-intercepted HTTPS)
    # Just attempt downloads directly with proper timeouts

    local download_success=false
    local temp_file="maldetect-latest.tar.gz"
    local best_source=""

    # Clean up any empty/partial files from previous failed attempts
    if [ -f "$temp_file" ] && [ ! -s "$temp_file" ]; then
        rm -f "$temp_file"
    fi

    # Download sources in priority order
    # Format: "name|url|label" (using | as delimiter to avoid splitting https://)
    # Note: Repository is rfxn/linux-malware-detect (not maldet)
    # Latest tested version: v2.0.1-rc4 (Apr 20, 2026)
    local sources=(
        "github-release|https://api.github.com/repos/rfxn/linux-malware-detect/tarball/v2.0.1-rc4|GitHub Release v2.0.1-rc4"
        "github-main|https://github.com/rfxn/linux-malware-detect/archive/refs/heads/main.tar.gz|GitHub main branch (Development)"
    )

    echo "Attempting to download from sources..."
    echo ""

    for source_info in "${sources[@]}"; do
        IFS='|' read -r source_name source_url source_label <<< "$source_info"

        echo "  Trying $source_label..."

        # Clean up any previous attempt file before trying
        rm -f "$temp_file"

        # Try download with aggressive timeout
        # --timeout: fail if no progress for this many seconds
        # --read-timeout: fail if no data received for this many seconds
        if wget -q --timeout=30 --read-timeout=10 -O "$temp_file" "$source_url" 2>/dev/null; then
            # Verify download created a non-empty file (wget creates empty file on failure)
            if [ -f "$temp_file" ] && [ -s "$temp_file" ]; then
                echo -e "  ${GREEN}✓ Download successful ($(du -h "$temp_file" | cut -f1))${NC}"
                download_success=true
                best_source="$source_label"
                break
            else
                # Download command succeeded but file is empty - network/proxy issue
                rm -f "$temp_file"
                echo -e "  ${RED}✗ Download created empty file (network/firewall issue)${NC}"
            fi
        else
            # wget command failed
            rm -f "$temp_file"
            echo -e "  ${RED}✗ Download failed${NC}"
        fi

        # Also try with curl as fallback
        if [ "$download_success" = false ]; then
            rm -f "$temp_file"

            if curl -f --connect-timeout 10 --max-time 30 -L -o "$temp_file" "$source_url" 2>/dev/null; then
                # Verify curl created a non-empty file
                if [ -f "$temp_file" ] && [ -s "$temp_file" ]; then
                    echo -e "  ${GREEN}✓ Download successful via curl ($(du -h "$temp_file" | cut -f1))${NC}"
                    download_success=true
                    best_source="$source_label"
                    break
                else
                    rm -f "$temp_file"
                    echo -e "  ${RED}✗ Curl created empty file (network/firewall issue)${NC}"
                fi
            else
                rm -f "$temp_file"
                echo -e "  ${RED}✗ Curl failed${NC}"
            fi
        fi
    done

    echo ""

    if [ "$download_success" = false ]; then
        # All sources timed out or failed - check for offline options
        echo -e "${YELLOW}All download sources failed or timed out.${NC}"
        echo ""
        echo "Checking for pre-downloaded archives or system packages..."
        echo ""

        # Check for pre-cached/pre-downloaded file
        local local_archive=""
        for path in /root/maldetect*.tar.gz /tmp/maldetect*.tar.gz /opt/maldetect*.tar.gz ~/maldetect*.tar.gz; do
            if [ -f "$path" ]; then
                local_archive="$path"
                echo -e "${GREEN}✓ Found archive: $path${NC}"
                break
            fi
        done

        if [ -n "$local_archive" ]; then
            echo ""
            echo "Using pre-downloaded archive: $local_archive"
            # Use archive directly without copying
            temp_file="$local_archive"

            # Validate the archive
            if [ -f "$temp_file" ] && [ -s "$temp_file" ]; then
                # Quick check: can we read it as tar?
                if tar -tzf "$temp_file" >/dev/null 2>&1; then
                    download_success=true
                    best_source="offline-archive"
                    echo -e "${GREEN}✓ Archive validated and ready for extraction${NC}"
                else
                    echo -e "${RED}✗ Archive is corrupted or not a valid tar file${NC}"
                    download_success=false
                    temp_file=""
                fi
            else
                echo -e "${RED}✗ Archive file is missing or empty${NC}"
                download_success=false
                temp_file=""
            fi
        else
            echo -e "${RED}✗ No local archive found${NC}"
            echo ""
            echo "All sources unreachable. To install Maldet, use one of these methods:"
            echo ""
            echo "  METHOD 1 - Download on networked machine and transfer:"
            echo "    On another server with internet:"
            echo "      wget https://www.rfxn.com/downloads/maldetect-latest.tar.gz"
            echo "    Then copy to this server:"
            echo "      scp maldetect-latest.tar.gz root@YOUR-SERVER:/root/"
            echo "    Then run this installer again"
            echo ""
            echo "  METHOD 2 - GitHub source as alternative:"
            echo "    wget https://github.com/rfxn/maldet/archive/refs/heads/main.tar.gz -O /root/maldetect.tar.gz"
            echo "    (then run this installer again)"
            echo ""
            echo "Once you place the archive in /root/ (or /tmp/ or /opt/), run installer again."
            echo ""
            read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
            return 1
        fi
    fi

    # Extract and install if we have a valid archive
    if [ "$download_success" = true ]; then
        if [ ! -f "$temp_file" ] || [ ! -s "$temp_file" ]; then
            echo -e "${RED}✗ Archive file missing or empty: $temp_file${NC}"
            return 1
        fi
        echo "Installing from $best_source..."
        echo ""

        # Extract and install
        echo "  Extracting archive..."
        if tar xzf "$temp_file" 2>/dev/null; then
            echo "  Running installer..."
            # Find the extracted directory (could be maldetect-* or rfxn-linux-malware-detect-*)
            local install_dir
            install_dir=$(find . -maxdepth 1 -type d \( -name "*malware*" -o -name "*maldet*" \) 2>/dev/null | head -1)

            if [ -n "$install_dir" ] && [ -f "$install_dir/install.sh" ]; then
                if cd "$install_dir" 2>/dev/null && bash install.sh > /tmp/maldet-install.log 2>&1; then
                    echo -e "  ${GREEN}✓ Maldet installed successfully${NC}"

                    # Update signatures in background
                    echo ""
                    echo "Updating malware signatures..."
                    if command -v maldet &>/dev/null; then
                        maldet -u > /dev/null 2>&1 &
                        echo "  (signatures updating in background)"
                    fi
                else
                    echo -e "  ${RED}✗ Installation failed. Check /tmp/maldet-install.log${NC}"
                fi
            else
                echo -e "  ${RED}✗ Could not find install.sh in extracted directory${NC}"
                if [ -z "$install_dir" ]; then
                    echo "  (Directory not found matching *malware* or *maldet*)"
                fi
            fi
            cd /tmp
            rm -rf maldetect-* rfxn-linux-malware-detect-* maldetect-latest.tar.gz 2>/dev/null || true
        else
            echo -e "  ${RED}✗ Failed to extract archive${NC}"
            rm -f "$temp_file"
        fi
    else
        echo -e "${RED}✗ No valid archive available for extraction${NC}"
    fi

    echo ""
    read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
}

install_clamav_only() {
    echo ""
    print_header "Installing ClamAV (Open Source Antivirus)"
    echo ""

    if is_clamav_installed; then
        echo -e "${GREEN}✓ ClamAV is already installed${NC}"
        echo ""
        read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
        return 0
    fi

    echo "Installing ClamAV and updating virus definitions..."
    echo ""

    if command -v yum &>/dev/null; then
        echo "Using yum package manager..."
        local install_log="/tmp/clamav-install-$$.log"
        if yum install -y clamav clamav-daemon clamav-update > "$install_log" 2>&1; then
            tail -5 "$install_log"
        else
            echo -e "${YELLOW}Installation returned non-zero exit code${NC}"
            tail -10 "$install_log"
        fi
        rm -f "$install_log"
    elif command -v apt-get &>/dev/null; then
        echo "Using apt package manager..."
        apt-get update > /dev/null 2>&1
        local install_log="/tmp/clamav-install-$$.log"
        if apt-get install -y clamav clamav-daemon > "$install_log" 2>&1; then
            tail -5 "$install_log"
        else
            echo -e "${YELLOW}Installation returned non-zero exit code${NC}"
            tail -10 "$install_log"
        fi
        rm -f "$install_log"
    else
        echo -e "${RED}✗ No compatible package manager found${NC}"
        echo ""
        read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
        return 1
    fi

    echo ""
    if is_clamav_installed; then
        echo -e "${GREEN}✓ ClamAV installed successfully${NC}"

        # Update signatures
        echo ""
        echo "Updating virus signatures..."
        for freshclam_path in /usr/bin/freshclam /usr/sbin/freshclam /usr/local/bin/freshclam; do
            if [ -x "$freshclam_path" ]; then
                timeout 60 "$freshclam_path" > /dev/null 2>&1 &
                echo "  (signatures updating in background)"
                break
            fi
        done
    else
        echo -e "${RED}✗ Installation may have failed${NC}"
    fi

    echo ""
    read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
}

install_rkhunter_only() {
    echo ""
    print_header "Installing RKHunter (Rootkit Detection)"
    echo ""

    if is_rkhunter_installed; then
        echo -e "${GREEN}✓ RKHunter is already installed${NC}"
        echo ""
        read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
        return 0
    fi

    echo "Installing RKHunter..."
    echo ""

    if command -v yum &>/dev/null; then
        echo "Using yum package manager..."
        yum install -y epel-release 2>&1 > /dev/null || true
        local install_log="/tmp/rkhunter-install-$$.log"
        if yum install -y rkhunter > "$install_log" 2>&1; then
            tail -3 "$install_log"
        else
            echo -e "${YELLOW}Installation returned non-zero exit code${NC}"
            tail -10 "$install_log"
        fi
        rm -f "$install_log"
    elif command -v apt-get &>/dev/null; then
        echo "Using apt package manager..."
        apt-get update > /dev/null 2>&1
        local install_log="/tmp/rkhunter-install-$$.log"
        if apt-get install -y rkhunter > "$install_log" 2>&1; then
            tail -3 "$install_log"
        else
            echo -e "${YELLOW}Installation returned non-zero exit code${NC}"
            tail -10 "$install_log"
        fi
        rm -f "$install_log"
    else
        echo -e "${RED}✗ No compatible package manager found${NC}"
        echo ""
        read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
        return 1
    fi

    echo ""
    if is_rkhunter_installed; then
        echo -e "${GREEN}✓ RKHunter installed successfully${NC}"
    else
        echo -e "${RED}✗ Installation may have failed${NC}"
    fi

    echo ""
    read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
}

# Install all scanners at once
install_all_scanners() {
    echo ""
    print_header "Install All Malware Scanners"

    echo "This will install:"
    echo "  • ClamAV (free, open source)"
    echo "  • Maldet (free, Linux-specific)"
    echo "  • ImunifyAV (FREE version)"
    echo "  • Rootkit Hunter (free, rootkit detection)"
    echo ""
    echo -e "${YELLOW}Note: ImunifyAV is FREE. Imunify360 is the paid version.${NC}"
    echo ""

    read -p "Proceed with installation? (yes/no): " confirm

    if [ "$confirm" != "yes" ]; then
        echo "Cancelled."
        read -p "Press Enter to continue..."
        return 0
    fi

    echo ""
    echo "=========================================="
    echo "Installing Scanners"
    echo "=========================================="
    echo ""

    # Install ClamAV
    if ! is_clamav_installed; then
        echo -e "${CYAN}[1/4] Installing ClamAV...${NC}"

        # Try control panel-specific methods first
        if [ -f "/usr/local/cpanel/cpanel" ]; then
            # cPanel method - use cPanel's package management only
            if rpm -qa 2>/dev/null | grep -q "cpanel-clamav" || true; then
                echo -e "${GREEN}✓ ClamAV already installed (cPanel)${NC}"
            else
                echo "  → Installing via cPanel package manager..."

                # Check if cPanel scripts exist before using them
                if [ -f "/scripts/update_local_rpm_versions" ] && [ -f "/scripts/check_cpanel_rpms" ]; then
                    /scripts/update_local_rpm_versions --edit target_settings.clamav installed 2>/dev/null || true
                    if ! /scripts/check_cpanel_rpms --fix --targets=clamav 2>&1 | tail -3; then
                        # cPanel scripts failed, fall back to standard yum
                        echo "  → cPanel package manager unavailable, trying standard yum..."
                        yum install -y clamav clamav-update 2>&1 | grep -E "Installing|Installed|already" || echo "  (installation in progress)"
                    fi
                else
                    # cPanel scripts don't exist, fall back to standard yum
                    echo "  → cPanel tools not available, using standard package manager..."
                    yum install -y clamav clamav-update 2>&1 | grep -E "Installing|Installed|already" || echo "  (installation in progress)"
                fi
            fi
            # IMPORTANT: Don't fall through to standard yum - cPanel packages conflict!
        elif [ -f "/usr/local/psa/version" ]; then
            # Plesk method - use standard package manager
            echo "  → Detected Plesk system, using standard package manager..."
            if command -v yum &>/dev/null; then
                yum install -y clamav clamav-update 2>&1 | grep -E "Installing|Installed|already installed" || echo "  (installation may already be complete)"
            elif command -v apt-get &>/dev/null; then
                apt-get update 2>&1 | grep -E "Reading|Building|Hit|Get" | head -3 || true
                apt-get install -y clamav clamav-daemon 2>&1 | grep -E "Setting up|already|newest" || echo "  (installation may already be complete)"
            fi
        elif command -v yum &>/dev/null; then
            # RHEL/CentOS based systems (non-cPanel)
            echo "  → Installing via yum..."
            yum install -y clamav clamav-update 2>&1 | grep -E "Installing|Installed|already installed" || echo "  (installation may already be complete)"
        elif command -v apt-get &>/dev/null; then
            # Debian/Ubuntu: Update package list first, then install ClamAV
            echo "  → Updating package list..."
            apt-get update 2>&1 | grep -E "Reading|Building|Hit|Get" | head -3 || true
            echo "  → Installing ClamAV..."
            apt-get install -y clamav clamav-daemon 2>&1 | grep -E "Setting up|already|newest" || echo "  (installation may already be complete)"
        fi

        if is_clamav_installed; then
            echo -e "${GREEN}✓ ClamAV installed${NC}"

            # Find freshclam binary - try standard locations first before using find
            local freshclam_bin=""
            for path in /usr/bin/freshclam /usr/sbin/freshclam \
                        /usr/local/bin/freshclam /usr/local/sbin/freshclam \
                        /usr/local/cpanel/3rdparty/bin/freshclam; do
                if [ -x "$path" ]; then
                    freshclam_bin="$path"
                    break
                fi
            done
            # Only use find as last resort if standard paths don't work
            if [ -z "$freshclam_bin" ]; then
                freshclam_bin=$(find /usr/local /usr -name freshclam -type f 2>/dev/null | head -1)
            fi

            # Update virus signatures immediately
            if [ -n "$freshclam_bin" ]; then
                echo "  → Updating virus signatures (timeout 60s)..."
                if timeout 60 "$freshclam_bin" 2>&1 | grep -qE "updated|Downloaded|up-to-date" || true; then
                    echo -e "  ${GREEN}✓${NC} Signatures updated"
                else
                    echo -e "  ${YELLOW}⚠${NC} Signature update inconclusive (may still be current)"
                fi
            fi
        else
            echo -e "${RED}✗ ClamAV installation failed${NC}"
        fi
    else
        echo -e "${GREEN}✓ ClamAV already installed${NC}"
    fi

    echo ""

    # Install Maldet
    if ! is_maldet_installed; then
        echo -e "${CYAN}[2/4] Installing Maldet...${NC}"

        (
            cd /tmp || { echo -e "${RED}✗ Cannot access /tmp${NC}"; return 1; }

            # Download Maldet
            echo "  → Downloading Maldet..."
            # Try HTTPS first (more secure), fallback to HTTP if needed
            if ! wget -q https://www.rfxn.com/downloads/maldetect-current.tar.gz 2>/dev/null; then
                if ! wget -q http://www.rfxn.com/downloads/maldetect-current.tar.gz; then
                    echo -e "${RED}✗ Download failed - check internet connectivity${NC}"
                    return 1
                fi
            fi

            if [ -f maldetect-current.tar.gz ]; then
                echo "  → Extracting archive..."
                if ! tar -xzf maldetect-current.tar.gz 2>/dev/null; then
                    echo -e "${RED}✗ Extraction failed - archive may be corrupted${NC}"
                    rm -f maldetect-current.tar.gz
                    return 1
                fi

                # Find the extracted directory
                local maldet_dir=$(find /tmp -maxdepth 1 -type d -name "maldetect-*" 2>/dev/null | head -1)
                if [ -z "$maldet_dir" ]; then
                    echo -e "${RED}✗ Cannot find extracted directory${NC}"
                    cd /tmp
                    rm -rf "maldetect-"*
                    return 1
                fi

                # Change to extracted directory
                if ! cd "$maldet_dir"; then
                    echo -e "${RED}✗ Cannot access directory: $maldet_dir${NC}"
                    cd /tmp
                    rm -rf "maldetect-"*
                    return 1
                fi

                # Run installation with error capture
                echo "  → Running installation script..."
                local install_log="/tmp/maldet-install-$$.log"
                if ./install.sh > "$install_log" 2>&1; then
                    install_exit=0
                else
                    install_exit=$?
                fi

                # Cleanup
                cd /tmp
                rm -rf "maldetect-"*

                # Check if installation succeeded
                if is_maldet_installed; then
                    # Verify we have version 2.0 or newer
                    local maldet_bin=$(command -v maldet || find /usr/local -name maldet -type f 2>/dev/null | head -1)
                    local maldet_version=""
                    if [ -n "$maldet_bin" ]; then
                        maldet_version=$("$maldet_bin" -v 2>/dev/null | grep -oE '[0-9]+\.[0-9]+' | head -1)
                    fi

                    # Check version is 2.0 or newer
                    if [ -n "$maldet_version" ]; then
                        local major_version=${maldet_version%%.*}
                        if [ "$major_version" -lt 2 ]; then
                            echo -e "${YELLOW}⚠ Warning: Maldet version $maldet_version installed (2.0+ recommended for performance)${NC}"
                        else
                            echo -e "${GREEN}✓${NC} Maldet $maldet_version installed (2.0+ performance optimizations)"
                        fi
                    else
                        echo -e "${GREEN}✓ Maldet installed${NC}"
                    fi

                    rm -f "$install_log"

                    # Update malware signatures immediately with timeout
                    echo "  → Updating malware signatures..."
                    if [ -n "$maldet_bin" ]; then
                        if timeout 120 "$maldet_bin" -u 2>&1 | grep -qE "update completed|signatures" || true; then
                            echo -e "  ${GREEN}✓${NC} Signatures updated"
                        else
                            echo -e "  ${YELLOW}⚠${NC} Signature update inconclusive (continuing with current definitions)"
                        fi
                    fi
                else
                    echo -e "${RED}✗ Maldet installation failed${NC}"

                    # Show diagnostic information
                    if [ -f "$install_log" ]; then
                        echo -e "${YELLOW}Installation output (last 10 lines):${NC}"
                        tail -10 "$install_log" | sed 's/^/  /'
                        echo ""
                        echo -e "${YELLOW}Full log saved to: $install_log${NC}"
                    fi
                fi
                return 0
            else
                echo -e "${RED}✗ Download failed - maldetect-current.tar.gz not found${NC}"
                return 0
            fi
        ) || true
    else
        echo -e "${GREEN}✓ Maldet already installed${NC}"
    fi

    echo ""

    # Install ImunifyAV (FREE version)
    if ! is_imunify_installed; then
        echo -e "${CYAN}[3/4] Installing ImunifyAV (FREE)...${NC}"
        echo "  This may take several minutes - please wait..."

        # ── STANDALONE DETECTION ─────────────────────────────────────────
        # Detect whether this is a standalone system (no cPanel, no Plesk).
        # InterWorx is also treated as standalone for ImunifyAV purposes
        # because imav-deploy.sh does not recognise it as a "panel".
        local imav_is_standalone=0
        if [ ! -f "/usr/local/cpanel/cpanel" ] && [ ! -f "/usr/local/psa/version" ]; then
            imav_is_standalone=1
        fi

        # ── STANDALONE: INTEGRATION.CONF SETUP ───────────────────────────
        if [ "$imav_is_standalone" -eq 1 ]; then
            echo ""
            echo -e "${YELLOW}  ⚠ Standalone system detected (no cPanel or Plesk found)${NC}"
            echo "  ImunifyAV requires a web server path for its UI on standalone systems."
            echo ""

            local imav_conf_dir="/etc/sysconfig/imunify360"
            local imav_conf_file="$imav_conf_dir/integration.conf"
            local imav_ui_path=""

            # Check if integration.conf already exists with ui_path set
            if [ -f "$imav_conf_file" ] && grep -q "^ui_path" "$imav_conf_file" 2>/dev/null; then
                # Already configured - read existing value for display only
                imav_ui_path=$(grep "^ui_path" "$imav_conf_file" | head -1 | cut -d'=' -f2 | tr -d ' ')
                echo -e "  ${GREEN}✓${NC} integration.conf already exists with ui_path: $imav_ui_path"
                echo "    Proceeding with existing configuration."
            else
                # Auto-detect web server document root (no prompting)
                local imav_detected_root
                imav_detected_root=$(get_web_root_for_imunify)
                imav_ui_path="$imav_detected_root/imunifyav"

                echo -e "  ${GREEN}✓${NC} Auto-detected web root: $imav_detected_root"
                echo "  UI will be deployed to: $imav_ui_path"
            fi

            # Create config directory if needed
            if [ "$imav_is_standalone" -ne 2 ]; then
                echo "  → Creating $imav_conf_dir ..."
                mkdir -p "$imav_conf_dir" || {
                    echo -e "${RED}  ✗ Cannot create $imav_conf_dir - check permissions. Skipping ImunifyAV.${NC}"
                    imav_is_standalone=2
                }
            fi

            # Write minimal integration.conf (only ui_path is required)
            if [ "$imav_is_standalone" -ne 2 ]; then
                printf '[paths]\nui_path = %s\n' "$imav_ui_path" > "$imav_conf_file" || {
                    echo -e "${RED}  ✗ Cannot write $imav_conf_file. Skipping ImunifyAV.${NC}"
                    imav_is_standalone=2
                }
            fi

            if [ "$imav_is_standalone" -ne 2 ]; then
                echo -e "  ${GREEN}✓${NC} integration.conf written: ui_path = $imav_ui_path"
            fi

            # SELinux warning for RHEL-family systems
            if [ "$imav_is_standalone" -ne 2 ] && command -v getenforce &>/dev/null; then
                local selinux_status
                selinux_status=$(getenforce 2>/dev/null || echo "Unknown")
                if [ "$selinux_status" = "Enforcing" ]; then
                    echo ""
                    echo -e "  ${YELLOW}⚠ SELinux is Enforcing${NC}"
                    echo "    After installation, ImunifyAV may need an SELinux policy module."
                    echo "    If the UI is inaccessible, run:"
                    echo "      ausearch -c 'imunify' | audit2allow -M imunify && semodule -i imunify.pp"
                fi
            fi

            echo ""
        fi
        # ── END STANDALONE SETUP ─────────────────────────────────────────

        # Only proceed with download/deploy if not cancelled (imav_is_standalone != 2)
        if [ "${imav_is_standalone:-0}" -ne 2 ]; then

            # Use deployment script method (most reliable)
            cd /tmp
            if [ -f "imav-deploy.sh" ]; then
                rm -f imav-deploy.sh
            fi

            # Download deployment script with timeout
            if timeout 30 wget -q -O imav-deploy.sh https://repo.imunify360.cloudlinux.com/defence360/imav-deploy.sh 2>/dev/null; then
                if [ ! -f imav-deploy.sh ] || [ ! -s imav-deploy.sh ]; then
                    echo -e "${RED}  Failed to download installation script (empty file)${NC}"
                else
                    # Run deployment script with timeout and capture output
                    echo "  → Running deployment script..."
                    local deploy_log="/tmp/imav-deploy-$$.log"
                    if timeout 300 bash imav-deploy.sh > "$deploy_log" 2>&1; then
                        # Check if any actual installation happened
                        if grep -qiE "installed|complete|success" "$deploy_log" || true; then
                            echo "  → Deployment script executed"
                        else
                            echo "  → Deployment script ran (check for errors below)"
                        fi

                        # Show any errors from deployment
                        if grep -qi "error\|failed\|conflict" "$deploy_log" || true; then
                            echo -e "  ${YELLOW}⚠ Warnings detected:${NC}"
                            grep -iE "error|failed|conflict" "$deploy_log" | sed 's/^/    /' | head -3
                        fi
                    else
                        echo -e "${YELLOW}  ⚠ Deployment script timed out or failed${NC}"
                    fi
                    rm -f "$deploy_log"
                    rm -f imav-deploy.sh

                    # Try to start the service if installed
                    if command -v systemctl &>/dev/null && is_imunify_installed; then
                        echo "  → Starting ImunifyAV service..."
                        systemctl start imunify-antivirus 2>/dev/null || true
                    fi
                fi
            else
                echo -e "${RED}  Failed to download installation script (network error or timeout)${NC}"
            fi

            if is_imunify_installed; then
                echo -e "${GREEN}✓ ImunifyAV (FREE) installed${NC}"
                echo "  No license key required - this is the FREE version"

                # Find imunify-antivirus binary
                local imunify_bin=$(command -v imunify-antivirus || find /usr -name imunify-antivirus 2>/dev/null | head -1)

                # Update malware signatures immediately
                if [ -n "$imunify_bin" ]; then
                    echo "  → Updating malware signatures..."
                    if timeout 60 "$imunify_bin" update 2>&1 | grep -qiE "updated|Success|completed" || true; then
                        echo -e "  ${GREEN}✓${NC} Signatures updated"
                    else
                        echo -e "  ${YELLOW}⚠${NC} Signature update inconclusive (continuing with current definitions)"
                    fi
                fi

                # ── STANDALONE: POST-INSTALL UI URL HINT ─────────────────
                if [ "$imav_is_standalone" -eq 1 ] && [ -n "${imav_ui_path:-}" ]; then
                    echo ""
                    echo -e "  ${CYAN}ImunifyAV UI path:${NC} $imav_ui_path"
                    echo "  Configure your web server to serve that directory, then"
                    echo "  access the UI at: http://YOUR-SERVER-IP/<ui_directory_name>/"
                    echo "  (Replace <ui_directory_name> with the last component of the path above)"
                fi
                # ── END POST-INSTALL HINT ─────────────────────────────────

            else
                echo -e "${RED}✗ ImunifyAV installation failed${NC}"
                if [ "$imav_is_standalone" -eq 1 ]; then
                    echo -e "${YELLOW}  Note: Verify integration.conf at $imav_conf_file is correct${NC}"
                    echo -e "${YELLOW}  and that $imav_ui_path is accessible by your web server.${NC}"
                else
                    echo -e "${YELLOW}  Note: ImunifyAV FREE is primarily supported on CloudLinux, cPanel, and Plesk systems${NC}"
                fi
            fi

        fi
        # ── END CANCELLED GUARD ───────────────────────────────────────────

    else
        echo -e "${GREEN}✓ ImunifyAV already installed${NC}"
    fi

    echo ""

    # Install Rootkit Hunter
    if ! is_rkhunter_installed; then
        echo -e "${CYAN}[4/4] Installing Rootkit Hunter...${NC}"

        # Ensure repo is enabled (OS-specific)
        if command -v dnf &>/dev/null; then
            # CentOS 8+, RHEL 8+, Fedora - use dnf as primary package manager
            if ! (rpm -qa 2>/dev/null | grep -q epel-release || false); then
                echo "  → Installing EPEL repository..."
                dnf install -y epel-release 2>&1 | grep -E "Installing|Installed|already installed" || echo "  (repo may already be enabled)"
            fi
            # Install rkhunter
            dnf install -y rkhunter 2>&1 | grep -E "Installing|Installed|already installed" || echo "  (installation may already be complete)"
        elif command -v yum &>/dev/null; then
            # CentOS 7, RHEL 7 - use yum
            if ! (rpm -qa 2>/dev/null | grep -q epel-release || false); then
                echo "  → Installing EPEL repository..."
                yum install -y epel-release 2>&1 | grep -E "Installing|Installed|already installed" || echo "  (repo may already be enabled)"
            fi
            # Install rkhunter
            yum install -y rkhunter 2>&1 | grep -E "Installing|Installed|already installed" || echo "  (installation may already be complete)"
        elif command -v apt-get &>/dev/null; then
            # Debian/Ubuntu - universe repo (rkhunter is in universe)
            echo "  → Ensuring universe repository is enabled..."
            if ! grep -q "universe" /etc/apt/sources.list 2>/dev/null; then
                # Add universe to existing deb lines (handles both HTTP and HTTPS)
                sed -i 's/^\(deb.*\) \(main\|restricted\)$/\1 \2 universe/' /etc/apt/sources.list 2>/dev/null || true
                apt-get update 2>&1 | grep -E "Hit|Get|Reading|Building" | head -3 || true
            fi

            apt-get install -y rkhunter 2>&1 | grep -E "Setting up|already|newest" || echo "  (installation may already be complete)"
        fi

        if is_rkhunter_installed; then
            echo -e "${GREEN}✓ Rootkit Hunter installed${NC}"

            # Update definitions
            echo "  → Updating rootkit definitions..."
            if timeout 120 rkhunter --update 2>&1 | grep -qE "updated|downloaded" || true; then
                echo -e "  ${GREEN}✓${NC} Definitions updated"
            else
                echo -e "  ${YELLOW}⚠${NC} Definitions update inconclusive (continuing)"
            fi

            # Initialize baseline (propupd creates file property database)
            echo "  → Initializing baseline database..."
            if timeout 300 rkhunter --propupd 2>&1 | grep -q "Updating" || timeout 300 rkhunter --propupd &>/dev/null; then
                echo -e "  ${GREEN}✓${NC} Baseline initialized"
            else
                echo -e "  ${YELLOW}⚠${NC} Baseline initialization inconclusive"
            fi
        else
            echo -e "${RED}✗ Rootkit Hunter installation failed${NC}"
        fi
    else
        echo -e "${GREEN}✓ Rootkit Hunter already installed${NC}"
    fi

    echo ""
    echo "=========================================="
    echo "Installation Complete"
    echo "=========================================="
    echo ""

    # Re-detect scanners
    detect_scanners

    echo ""
    read -p "Press Enter to continue..."
}

# Detect control panel and gather docroots
detect_control_panel() {
    docroot_array=()

    # Use system-detect.sh if available, otherwise detect
    if [ -n "$SYS_CONTROL_PANEL" ]; then
        CONTROL_PANEL="$SYS_CONTROL_PANEL"
    elif [ -f "/etc/userdatadomains" ]; then
        CONTROL_PANEL="cpanel"
    elif [ -f "/usr/local/psa/version" ]; then
        CONTROL_PANEL="plesk"
    elif [ -d "/usr/local/interworx/" ]; then
        CONTROL_PANEL="interworx"
    else
        CONTROL_PANEL="none"
    fi

    # cPanel-specific setup
    if [ "$CONTROL_PANEL" = "cpanel" ]; then
        # Add cPanel 3rdparty bin to PATH only for cPanel
        export PATH=/usr/local/cpanel/3rdparty/bin/:$PATH

        while IFS= read -r line; do
            # Format: domain: user==owner==main==domain==docroot==...
            # Extract docroot (field 5, 0-indexed field 4) using awk directly
            docroot=$(awk -F'==' '{print $5}' <<< "$line")
            [ -n "$docroot" ] && [ -d "$docroot" ] && docroot_array+=("$docroot")
        done < <(cut -d: -f2- /etc/userdatadomains | sort -u)

    # Plesk-specific
    elif [ "$CONTROL_PANEL" = "plesk" ]; then
        while IFS= read -r domain; do
            docroot=$(plesk bin site -i "$domain" 2>/dev/null | grep "WWW-Root" | awk '{print $2}')
            [ -n "$docroot" ] && docroot_array+=("$docroot")
        done < <(plesk bin site --list 2>/dev/null)

    # InterWorx-specific (improved with proper path structure)
    elif [ "$CONTROL_PANEL" = "interworx" ]; then
        # InterWorx structure: /home/username/domain.com/html
        # Find all html directories in the InterWorx structure
        while IFS= read -r docroot; do
            [ -n "$docroot" ] && [ -d "$docroot" ] && docroot_array+=("$docroot")
        done < <(find /home/*/*/html -maxdepth 0 -type d 2>/dev/null | sort -u)

    else
        CONTROL_PANEL="none"
        echo -e "${YELLOW}No control panel detected${NC}"
        echo "Manual path selection required"
        return 1
    fi

    # Remove subdirectory docroots (avoid scanning same files twice)
    sanitize_docroots

    return 0
}

# Remove subdirectory docroots from array (optimized single-pass algorithm)
sanitize_docroots() {
    sanitized_docroot=()

    # For each docroot, check if it's a parent of any other docroot
    for current in "${docroot_array[@]}"; do
        is_subdir=0

        # Check if current path is a subdirectory of any other path
        for other in "${docroot_array[@]}"; do
            # Use [[ ]] for substring matching (safe, doesn't use regex)
            if [[ "$current" != "$other" && "$current" == "$other"/* ]]; then
                is_subdir=1
                break
            fi
        done

        # Only add if it's NOT a subdirectory of another path
        if [ $is_subdir -eq 0 ]; then
            sanitized_docroot+=("$current")
        fi
    done
}

# Get docroots for specific user
get_user_docroots() {
    local username="$1"
    local user_docroots=()

    if [ "$CONTROL_PANEL" = "cpanel" ]; then
        while IFS= read -r line; do
            docroot=$(awk -F'==' '{print $5}' <<< "$line")
            [ -n "$docroot" ] && [ -d "$docroot" ] && user_docroots+=("$docroot")
        done < <(grep -F ":${username}==" /etc/userdatadomains | cut -d: -f2- | sort -u)
    elif [ "$CONTROL_PANEL" = "interworx" ]; then
        # Use user-manager.sh to get all domains for this user
        local domains=$(get_user_domains "$username")
        if [ -n "$domains" ]; then
            while IFS= read -r domain; do
                # InterWorx: /home/username/domain.com/html
                local docroot="/home/${username}/${domain}/html"
                [ -d "$docroot" ] && user_docroots+=("$docroot")
            done <<< "$domains"
        fi
    else
        echo -e "${RED}User-specific scanning only supported on cPanel/InterWorx${NC}"
        return 1
    fi

    echo "${user_docroots[@]}"
}

# Get docroot for specific domain
get_domain_docroot() {
    local domain="$1"
    local domain_docroot=""

    if [ "$CONTROL_PANEL" = "cpanel" ]; then
        # Use grep with word boundary for safe matching (avoid regex injection)
        domain_docroot=$(grep "^$(printf '%s\n' "$domain" | sed 's/[[\.*^$/]/\\&/g'):" /etc/userdatadomains | cut -d= -f5 | sed 's/==/=/g')
    elif [ "$CONTROL_PANEL" = "plesk" ]; then
        domain_docroot=$(plesk bin site -i "$domain" 2>/dev/null | grep "WWW-Root" | awk '{print $2}')
    elif [ "$CONTROL_PANEL" = "interworx" ]; then
        # Find which user owns this domain using vhost configs
        # Use safer approach - validate glob results before processing
        local username=""
        for conf_file in /etc/httpd/conf.d/vhost_*.conf; do
            [ -f "$conf_file" ] || continue
            if grep -qF "ServerName ${domain}" "$conf_file" 2>/dev/null; then
                username=$(grep "SuexecUserGroup" "$conf_file" 2>/dev/null | awk '{print $2}' | head -1)
                [ -n "$username" ] && break
            fi
        done
        if [ -n "$username" ]; then
            # InterWorx: /home/username/domain.com/html
            domain_docroot="/home/${username}/${domain}/html"
        fi
    else
        echo -e "${RED}Domain lookup only supported on cPanel/Plesk/InterWorx${NC}"
        return 1
    fi

    echo "$domain_docroot"
}

# Memory check before scanning
check_memory() {
    local total_mem=$(free -m | awk '/^Mem:/{print $2}')
    local avail_mem=$(free -m | awk '/^Mem:/{print $7}')

    local min_total=2048  # 2GB
    local min_avail=512   # 512MB

    if [ "$total_mem" -lt "$min_total" ] || [ "$avail_mem" -lt "$min_avail" ]; then
        echo -e "${YELLOW}WARNING: Low memory detected${NC}"
        echo "Total: ${total_mem}MB | Available: ${avail_mem}MB"
        echo ""
        echo "Running a full scan may cause high load or OOM conditions."
        echo ""
        read -p "Continue anyway? (yes/no): " confirm

        if [ "$confirm" != "yes" ]; then
            echo "Scan cancelled"
            return 1
        fi
    fi

    return 0
}

# ImunifyAV scanner

# Generate standalone malware scan script
generate_standalone_scanner() {
    local scan_paths=("$@")

    if [ ${#scan_paths[@]} -eq 0 ]; then
        echo -e "${RED}No paths to scan${NC}"
        return 1
    fi

    # Create session ID and directory
    local session_id="malware-$(date +%Y%m%d-%H%M%S)"
    local session_dir="/opt/${session_id}"

    echo ""
    print_header "Generating Standalone Scanner"
    echo "Session ID: $session_id"
    echo "Location: $session_dir"
    echo ""

    # Create directory structure
    mkdir -p "$session_dir"/{logs,results}

    # Create standalone scan script
    cat > "$session_dir/scan.sh" << 'STANDALONE_EOF'
#!/bin/bash
set -o pipefail

################################################################################
# Standalone Malware Scanner
################################################################################
# Auto-generated by Server Management Toolkit
# This script is self-contained and can run independently
################################################################################

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

# MALDET_ONLY mode (injected from parent shell - for dedicated Maldet menu)
MALDET_ONLY="PLACEHOLDER_MALDET_ONLY"

# Detect control panel (for IP reputation tracking)
if [ -z "$CONTROL_PANEL" ]; then
    if [ -f "/usr/local/cpanel/version" ]; then
        CONTROL_PANEL="cpanel"
    elif [ -f "/usr/local/psa/version" ]; then
        CONTROL_PANEL="plesk"
    elif [ -d "/home/interworx" ] || [ -f "/usr/bin/iworx-helper" ] || ([ -d "/chroot/home" ] && [ -f "/usr/bin/nodeworx" ]); then
        CONTROL_PANEL="interworx"
    else
        CONTROL_PANEL="standalone"
    fi
fi

# Detect log directory based on control panel
if [ -z "$SYS_LOG_DIR" ]; then
    case "$CONTROL_PANEL" in
        cpanel) SYS_LOG_DIR="/var/log/apache2/domlogs" ;;
        plesk) SYS_LOG_DIR="/var/www/vhosts/system" ;;
        interworx) SYS_LOG_DIR="/home" ;;
        *) SYS_LOG_DIR="/var/log" ;;
    esac
fi

# Detect user home base directory based on control panel
if [ -z "$SYS_USER_HOME_BASE" ]; then
    case "$CONTROL_PANEL" in
        cpanel) SYS_USER_HOME_BASE="/home" ;;
        plesk) SYS_USER_HOME_BASE="/var/www/vhosts" ;;
        interworx) SYS_USER_HOME_BASE="/chroot/home" ;;
        *) SYS_USER_HOME_BASE="/home" ;;
    esac
fi

# Get script directory
SCAN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_DIR="$SCAN_DIR/logs"
RESULTS_DIR="$SCAN_DIR/results"

# Create log and results directories
mkdir -p "$LOG_DIR" "$RESULTS_DIR"

# Session info
SESSION_LOG="$LOG_DIR/session.log"
SUMMARY_FILE="$RESULTS_DIR/summary.txt"
INFECTED_LIST="$RESULTS_DIR/infected_files.txt"

# Logging function
log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$SESSION_LOG"
}

# Confirm user action (y/n prompt)
confirm() {
    local prompt="$1"
    local response
    read -t 10 -p "$prompt (y/n): " response </dev/tty 2>/dev/null || response="n"
    [[ "$response" =~ ^[Yy]$ ]]
}

# Activity spinner for long-running scans
show_spinner() {
    local pid=$1
    local message=$2
    local spin='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
    local i=0

    while kill -0 "$pid" 2>/dev/null; do
        i=$(( (i+1) % 10 ))
        printf "\r  ⏳ %s %s " "$message" "${spin:$i:1}"
        sleep 0.2
    done
    printf "\r  ✓ %s - Complete\n" "$message"
}

# Format elapsed time
format_time() {
    local seconds=$1
    if [ "$seconds" -lt 60 ]; then
        echo "${seconds}s"
    elif [ "$seconds" -lt 3600 ]; then
        printf "%dm %ds" $((seconds / 60)) $((seconds % 60))
    else
        printf "%dh %dm" $((seconds / 3600)) $(((seconds % 3600) / 60))
    fi
}

# Cleanup function for trap handler
cleanup_on_exit() {
    local exit_code=$?
    echo ""

    # Remove running marker file
    rm -f "$SCAN_DIR/.scan_running"

    # Only log if session log exists
    if [ -f "$SESSION_LOG" ]; then
        log_message "Cleanup triggered (exit code: $exit_code)"
    fi

    # Remove temporarily installed RKHunter
    if [ "${RKHUNTER_TEMP_INSTALLED:-false}" = "true" ]; then
        if [ -f "$SESSION_LOG" ]; then
            log_message "Removing temporarily installed RKHunter..."
        fi
        echo "→ Cleaning up: Removing Rootkit Hunter..."
        if command -v yum &>/dev/null; then
            if yum remove -y rkhunter &>/dev/null 2>&1; then
                if [ -f "$SESSION_LOG" ]; then
                    log_message "RKHunter removed successfully"
                fi
            else
                if [ -f "$SESSION_LOG" ]; then
                    log_message "WARNING: Failed to remove RKHunter (yum command failed)"
                fi
            fi
        elif command -v apt-get &>/dev/null; then
            if apt-get remove -y rkhunter &>/dev/null 2>&1; then
                if [ -f "$SESSION_LOG" ]; then
                    log_message "RKHunter removed successfully"
                fi
            else
                if [ -f "$SESSION_LOG" ]; then
                    log_message "WARNING: Failed to remove RKHunter (apt-get command failed)"
                fi
            fi
        fi
    fi

    # Save interrupted status (only if summary file directory exists)
    if [ "$exit_code" -ne 0 ] && [ -d "$RESULTS_DIR" ]; then
        {
            echo ""
            echo "SCAN INTERRUPTED"
            echo "Exit code: $exit_code"
            echo "Time: $(date)"
        } >> "$SUMMARY_FILE"
        if [ -f "$SESSION_LOG" ]; then
            log_message "Scan interrupted with exit code: $exit_code"
        fi
    fi
}

# Set trap for cleanup on exit, interrupt, or termination
trap cleanup_on_exit EXIT INT TERM

# Banner
clear
echo "========================================"
echo "Standalone Malware Scanner"
echo "========================================"
echo "Session: ${SCAN_DIR##*/}"
echo "Started: $(date)"
echo "========================================"
echo ""

log_message "Scan session started"

# Create marker file to indicate scan is running
touch "$SCAN_DIR/.scan_running"

# Detect available scanners (consolidate into lowercase array)
available_scanners=()

if command -v imunify-antivirus &>/dev/null; then
    available_scanners+=("imunify")
    log_message "Detected: ImunifyAV"
fi

if command -v clamscan &>/dev/null; then
    available_scanners+=("clamav")
    log_message "Detected: ClamAV"
fi

if command -v maldet &>/dev/null; then
    available_scanners+=("maldet")
    log_message "Detected: Maldet"
fi

# Track if rkhunter was auto-installed (for cleanup)
RKHUNTER_TEMP_INSTALLED=false

if command -v rkhunter &>/dev/null; then
    available_scanners+=("rkhunter")
    log_message "Detected: Rootkit Hunter"
else
    # Auto-install rkhunter temporarily for this scan
    log_message "RKHunter not found - installing temporarily..."
    echo "→ Installing Rootkit Hunter (temporary, will be removed after scan)..."

    if command -v yum &>/dev/null; then
        # Ensure EPEL is available for RHEL-based systems
        if ! (rpm -qa | grep -q epel-release || false); then
            log_message "RKHunter: Installing EPEL repository..."
            yum install -y epel-release &>/dev/null || log_message "WARNING: EPEL install failed"
        fi

        # Install rkhunter via yum
        log_message "RKHunter: Installing via yum..."
        if yum install -y rkhunter &>/dev/null; then
            # Update definitions and initialize baseline
            if rkhunter --update &>/dev/null; then
                log_message "RKHunter: Database update successful"
            else
                log_message "WARNING: RKHunter database update failed"
            fi
            if rkhunter --propupd &>/dev/null; then
                log_message "RKHunter: Property baseline created"
            else
                log_message "WARNING: RKHunter property baseline creation failed"
            fi

            available_scanners+=("rkhunter")
            RKHUNTER_TEMP_INSTALLED=true
            log_message "RKHunter installed temporarily"
            echo "  ✓ RKHunter installed (will be removed after scan)"
        else
            log_message "WARNING: RKHunter yum install failed"
        fi
    elif command -v apt-get &>/dev/null; then
        # Install rkhunter via apt-get on Debian-based systems
        log_message "RKHunter: Installing via apt-get..."
        if apt-get update &>/dev/null && apt-get install -y rkhunter &>/dev/null; then
            # Update definitions and initialize baseline
            if rkhunter --update &>/dev/null; then
                log_message "RKHunter: Database update successful"
            else
                log_message "WARNING: RKHunter database update failed"
            fi
            if rkhunter --propupd &>/dev/null; then
                log_message "RKHunter: Property baseline created"
            else
                log_message "WARNING: RKHunter property baseline creation failed"
            fi

            available_scanners+=("rkhunter")
            RKHUNTER_TEMP_INSTALLED=true
            log_message "RKHunter installed temporarily"
            echo "  ✓ RKHunter installed (will be removed after scan)"
        else
            log_message "WARNING: RKHunter apt-get install failed"
        fi
    else
        log_message "WARNING: Neither yum nor apt-get found - cannot auto-install RKHunter"
    fi
fi

# Filter scanners if MALDET_ONLY is set (for Maldet-specific menu)
if [ "${MALDET_ONLY:-0}" = "1" ]; then
    log_message "Maldet-only mode enabled"
    echo "Running Maldet-only scan (fastest, Linux-focused)"
    echo ""
    # Check if Maldet is available
    if [[ " ${available_scanners[@]} " =~ " maldet " ]]; then
        available_scanners=("maldet")
        log_message "Filtered to Maldet only"
    else
        log_message "ERROR: Maldet not installed but MALDET_ONLY was set"
        echo -e "${RED}ERROR: Maldet is not installed${NC}"
        read -p "Press Enter to continue..." < /dev/tty 2>/dev/null || true
        return 1
    fi
fi

# If no scanners found, show installation guide and exit gracefully
if [ ${#available_scanners[@]} -eq 0 ]; then
    log_message "WARNING: No scanners found on this system"
    echo ""
    echo -e "${RED}No malware scanners detected!${NC}"
    echo ""
    echo -e "${YELLOW}Available Malware Scanners:${NC}"
    echo ""

    echo -e "${CYAN}ImunifyAV${NC} - FREE real-time malware scanner"
    echo "  Status: Not installed"
    echo "  Installation (cPanel):"
    echo "    yum install imunify-antivirus imunify-antivirus-cpanel"
    echo "    /opt/alt/python35/share/imunify360/scripts/av-userside-plugin.sh"
    echo "  Installation (manual):"
    echo "    wget https://repo.imunify360.cloudlinux.com/defence360/imav-deploy.sh"
    echo "    bash imav-deploy.sh"
    echo "  Docs: https://docs.imunify360.com/imunifyav/"
    echo ""

    echo -e "${CYAN}ClamAV${NC} - Open source antivirus engine"
    echo "  Status: Not installed"
    echo "  Installation:"
    echo "    yum install clamav clamav-update  # RHEL/CentOS"
    echo "    apt-get install clamav clamav-daemon  # Debian/Ubuntu"
    echo ""

    echo -e "${CYAN}Maldet (LMD)${NC} - Linux Malware Detect"
    echo "  Status: Not installed"
    echo "  Installation:"
    echo "    cd /tmp && wget http://www.rfxn.com/downloads/maldetect-current.tar.gz"
    echo "    tar -xzf maldetect-current.tar.gz && cd maldetect-*"
    echo "    ./install.sh"
    echo ""

    echo -e "${CYAN}Rootkit Hunter${NC} - Rootkit/backdoor/exploit scanner"
    echo "  Status: Not installed"
    echo "  Installation:"
    echo "    yum install epel-release rkhunter  # RHEL/CentOS"
    echo "    apt-get install rkhunter  # Debian/Ubuntu"
    echo ""

    echo -e "${YELLOW}Recommendation:${NC} Install at least ClamAV + RKHunter (both free)"
    echo ""
    exit 0
fi

log_message "Found ${#available_scanners[@]} scanner(s): ${available_scanners[*]}"

# Scan paths (will be replaced)
SCAN_PATHS=()
PLACEHOLDER_SCAN_PATHS

# Validate scan paths
log_message "Validating scan paths..."
VALID_PATHS=()
for path in "${SCAN_PATHS[@]}"; do
    if [ -e "$path" ]; then
        if [ -r "$path" ]; then
            VALID_PATHS+=("$path")
            log_message "✓ Valid path: $path"
        else
            log_message "WARNING: Path not readable: $path (skipping)"
            echo "⚠️  WARNING: Cannot read $path (permission denied) - skipping"
        fi
    else
        log_message "WARNING: Path does not exist: $path (skipping)"
        echo "⚠️  WARNING: Path does not exist: $path - skipping"
    fi
done

if [ ${#VALID_PATHS[@]} -eq 0 ]; then
    log_message "ERROR: No valid paths to scan!"
    echo -e "${RED}ERROR: No valid paths to scan!${NC}"
    exit 1
fi

# Use only valid paths
SCAN_PATHS=("${VALID_PATHS[@]}")
log_message "Scanning ${#SCAN_PATHS[@]} valid path(s)"

# Check available disk space for logs
log_message "Checking disk space..."
SCAN_DIR_FS=$(df -P "$SCAN_DIR" | tail -1 | awk '{print $6}')
AVAILABLE_KB=$(df -P "$SCAN_DIR" | tail -1 | awk '{print $4}')
AVAILABLE_MB=$((AVAILABLE_KB / 1024))

if [ "$AVAILABLE_MB" -lt 100 ]; then
    log_message "WARNING: Low disk space ($AVAILABLE_MB MB available)"
    echo "⚠️  WARNING: Low disk space on $SCAN_DIR_FS ($AVAILABLE_MB MB available)"
    echo "Scan logs may be large. Recommend at least 100 MB free space."
    echo ""
    read -t 10 -p "Continue anyway? (y/N): " continue_scan </dev/tty 2>/dev/null || continue_scan="n"
    if [[ ! "$continue_scan" =~ ^[Yy]$ ]]; then
        log_message "Scan cancelled due to low disk space"
        echo "Scan cancelled."
        exit 0
    fi
else
    log_message "Disk space OK: $AVAILABLE_MB MB available"
fi

# Initialize summary
{
    echo "=========================================="
    echo "Malware Scan Summary Report"
    echo "=========================================="
    echo "Session: ${SCAN_DIR##*/}"
    echo "Started: $(date)"
    echo "Scanners: ${available_scanners[*]}"
    echo "Paths: ${#SCAN_PATHS[@]}"
    echo ""
    printf '%s\n' "${SCAN_PATHS[@]}"
    echo ""
    echo "=========================================="
    echo ""
} > "$SUMMARY_FILE"

# Track completion
SCANNERS_COMPLETED=0
TOTAL_SCANNERS=${#available_scanners[@]}

# Run each scanner
for scanner in "${available_scanners[@]}"; do
    SCANNER_NUM=$((SCANNERS_COMPLETED + 1))

    echo ""
    echo ""
    echo "=========================================="
    echo -e "${CYAN}${BOLD}Scanner $SCANNER_NUM of $TOTAL_SCANNERS: ${scanner^}${NC}"
    echo "=========================================="
    echo ""
    log_message "Starting ${scanner} scan ($SCANNER_NUM/$TOTAL_SCANNERS)"

    {
        echo "Scanner: ${scanner^}"
        echo "Started: $(date)"
        echo "---"
    } >> "$SUMMARY_FILE"

    case "$scanner" in
        imunify)
            # ImunifyAV has built-in exclusions that prevent comprehensive system scanning
            # Only use ImunifyAV for user-focused scans (not full server scans)
            if [ "${#SCAN_PATHS[@]}" -eq 1 ] && [ "${SCAN_PATHS[0]}" = "/" ]; then
                echo ""
                echo "ℹ️  Skipping ImunifyAV for full server scan"
                echo "   Reason: ImunifyAV has built-in exclusions that skip system directories"
                echo "   ClamAV and Maldet will provide comprehensive coverage instead"
                echo ""
                log_message "ImunifyAV: Skipped (not suitable for full server scans - use ClamAV/Maldet instead)"
                {
                    echo "⊘ ImunifyAV scan skipped (not suitable for full system scans)"
                } >> "$SUMMARY_FILE"
                continue
            fi

            SCAN_START=$(date +%s)
            log_message "ImunifyAV: Updating signatures"

            if ! timeout 300 imunify-antivirus update &>> "$LOG_DIR/imunify.log"; then
                log_message "WARNING: ImunifyAV update failed (continuing with existing signatures)"
                echo "⚠️  WARNING: Signature update failed, using existing signatures"
            fi

            log_message "ImunifyAV: Starting on-demand scan"
            echo ""
            echo "  📁 Scanning paths: ${SCAN_PATHS[*]}"
            echo "  ⏳ Scanner: ImunifyAV"
            echo ""

            IMUNIFY_INFECTED=0

            # Run ImunifyAV scan with timeout (2 hours max)
            # Use --output-format to make parsing easier, with --timeout to prevent hanging
            for path in "${SCAN_PATHS[@]}"; do
                if [ ! -d "$path" ]; then
                    log_message "ImunifyAV: Skipping non-existent path: $path"
                    continue
                fi

                log_message "ImunifyAV: Scanning $path"
                echo "  Scanning: $path"

                # Run scan with timeout to prevent hanging on status checks
                # ImunifyAV scan - use 'queue put' command with path as positional argument
                timeout 7200 imunify-antivirus malware on-demand queue put "$path" &>> "$LOG_DIR/imunify.log" &
                IMUNIFY_PID=$!

                # Monitor with simple timeout (don't try to parse imunify status which hangs)
                if [ -n "$IMUNIFY_PID" ] && kill -0 "$IMUNIFY_PID" 2>/dev/null; then
                    wait "$IMUNIFY_PID"
                    IMUNIFY_EXIT=$?
                else
                    log_message "ERROR: ImunifyAV PID not found for $path"
                    IMUNIFY_EXIT=1
                fi

                if [ "$IMUNIFY_EXIT" -eq 124 ]; then
                    log_message "ERROR: ImunifyAV scan timed out after 2 hours for $path"
                    echo "  ⏱️  Scan timed out (2 hour limit)"
                elif [ "$IMUNIFY_EXIT" -ne 0 ]; then
                    log_message "WARNING: ImunifyAV scan exited with code $IMUNIFY_EXIT for $path"
                    echo "  ⚠️  Scan completed with code $IMUNIFY_EXIT"
                fi
            done

            # Try to get count of malicious files from malicious list (if available)
            # FIXED Issue 4B: Defensive header detection
            malicious_output=$(timeout 60 imunify-antivirus malware malicious list 2>/dev/null)
            IMUNIFY_MALICIOUS_EXIT=$?

            IMUNIFY_INFECTED=0
            # FIXED Issue 4A: Distinguish timeout from other errors
            case "$IMUNIFY_MALICIOUS_EXIT" in
                0)
                    # Success - validate the output and count lines
                    if [ -n "$malicious_output" ]; then
                        # Check if first line looks like header (contains "Path", "ID", "Threat", etc.)
                        first_line="${malicious_output%%$'\n'*}"
                        if [[ "$first_line" == *"Path"* ]] || [[ "$first_line" == *"ID"* ]] || [[ "$first_line" == *"Threat"* ]]; then
                            IMUNIFY_INFECTED=$(printf '%s\n' "$malicious_output" | tail -n +2 | wc -l)
                        else
                            IMUNIFY_INFECTED=$(printf '%s\n' "$malicious_output" | wc -l)
                        fi
                        # Ensure it's numeric
                        if ! [[ "$IMUNIFY_INFECTED" =~ ^[0-9]+$ ]]; then
                            IMUNIFY_INFECTED=0
                        fi
                    fi
                    ;;
                124)
                    log_message "WARNING: ImunifyAV malicious list command timed out after 60s"
                    IMUNIFY_INFECTED=0
                    ;;
                *)
                    log_message "WARNING: Failed to get ImunifyAV malicious count (exit: $IMUNIFY_MALICIOUS_EXIT)"
                    IMUNIFY_INFECTED=0
                    ;;
            esac

            SCAN_END=$(date +%s)
            DURATION=$((SCAN_END - SCAN_START))
            echo "  ✓ ImunifyAV scan complete"
            echo "  ⏱️  Duration: ${DURATION}s"
            echo ""
            echo "✓ ImunifyAV scan complete - Found: $IMUNIFY_INFECTED | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE"
            log_message "ImunifyAV: Scan complete - $IMUNIFY_INFECTED malicious files in ${DURATION}s"
            ;;

        clamav)
            SCAN_START=$(date +%s)
            if command -v freshclam &>/dev/null; then
                log_message "ClamAV: Updating signatures"
                if ! freshclam &>> "$LOG_DIR/clamav.log"; then
                    log_message "WARNING: ClamAV signature update failed (continuing with existing signatures)"
                    echo "⚠️  WARNING: Signature update failed, using existing signatures"
                fi
            fi

            log_message "ClamAV: Starting scan with activity monitoring"
            echo ""
            echo "  📁 Scanning path(s): ${SCAN_PATHS[*]}"
            echo "  ⏳ Scanner: ClamAV (comprehensive virus scan...)"
            echo ""

            # ClamAV returns 1 if infected files found, 0 if clean, >1 for errors
            # Run in background with timeout (2 hours) and activity monitoring
            timeout 7200 clamscan --infected --recursive "${SCAN_PATHS[@]}" &>> "$LOG_DIR/clamav.log" &
            CLAM_PID=$!

            # Monitor activity by watching log file growth
            last_size=0
            last_filename=""
            stall_counter=0

            while kill -0 "$CLAM_PID" 2>/dev/null; do
                # Get current log size and file count from log
                if [ -f "$LOG_DIR/clamav.log" ]; then
                    # FIXED Issue 5B: Improved error handling for stat
                    current_size=$(stat -c%s "$LOG_DIR/clamav.log" 2>/dev/null)
                    if [ -z "$current_size" ]; then
                        current_size=0
                    fi

                    # Try to get current file being scanned (FIXED Issue 5A: simpler, more robust pattern)
                    current_file=$(grep -oE '\./[^ ]+|/[^ ]+' "$LOG_DIR/clamav.log" 2>/dev/null | tail -1)
                    if [ -n "$current_file" ]; then
                        filename=${current_file##*/}

                        # Only update display when filename changes
                        if [ "$filename" != "$last_filename" ]; then
                            elapsed=$(($(date +%s) - SCAN_START))
                            printf "\r  Scanning: %s | Elapsed: %s  " \
                                "${filename:0:50}" "$(format_time "$elapsed")"
                            last_filename="$filename"
                        fi
                    fi

                    # Check for stalled scan (no log growth in 60 seconds)
                    if [ "$current_size" -eq "$last_size" ]; then
                        stall_counter=$((stall_counter + 1))
                        if [ "$stall_counter" -eq 300 ]; then  # 60 seconds (300 * 0.2s) - log only once
                            log_message "WARNING: ClamAV scan appears stalled (no activity for 60s)"
                        fi
                    else
                        stall_counter=0
                    fi
                    last_size=$current_size
                fi

                sleep 0.2
            done

            # Wait for scan to complete and get exit code
            if [ -n "$CLAM_PID" ] && kill -0 "$CLAM_PID" 2>/dev/null; then
                wait "$CLAM_PID"
                CLAM_EXIT=$?
            else
                log_message "ERROR: ClamAV PID not found (scan process may have exited prematurely)"
                CLAM_EXIT=1
            fi
            echo ""  # New line after spinner

            if [ "$CLAM_EXIT" -eq 124 ]; then
                log_message "ERROR: ClamAV scan timed out after 2 hours"
                echo "  ⏱️  Scan timed out (exceeded 2 hour limit)"
                echo "ClamAV scan timed out" >> "$SUMMARY_FILE"
                SCAN_END=$(date +%s)
                DURATION=$((SCAN_END - SCAN_START))
                echo ""
                continue
            elif [ "$CLAM_EXIT" -gt 1 ]; then
                log_message "ERROR: ClamAV scan failed with exit code $CLAM_EXIT"
                echo "  ✗ Scan failed (exit code: $CLAM_EXIT) - check logs"
                echo "ClamAV scan failed (exit code: $CLAM_EXIT)" >> "$SUMMARY_FILE"
                SCAN_END=$(date +%s)
                DURATION=$((SCAN_END - SCAN_START))
                echo ""
                continue
            fi

            # Extract infected files (FIXED: acceptable current approach)
            grep "FOUND" "$LOG_DIR/clamav.log" 2>/dev/null | cut -d: -f1 >> "$INFECTED_LIST" 2>/dev/null || true

            # Get scan stats from log (FIXED Issue 1B: robust number extraction independent of column position)
            CLAMAV_FILES_SCANNED=$(grep "Scanned files:" "$LOG_DIR/clamav.log" 2>/dev/null | tail -1 | grep -oE '[0-9]+' | head -1 || echo "0")
            CLAM_INFECTED=$(grep -c "FOUND" "$LOG_DIR/clamav.log" 2>/dev/null) || CLAM_INFECTED=0

            # Validate numbers (ensure they're numeric)
            if ! [[ "$CLAMAV_FILES_SCANNED" =~ ^[0-9]+$ ]]; then
                CLAMAV_FILES_SCANNED=0
            fi

            SCAN_END=$(date +%s)
            DURATION=$((SCAN_END - SCAN_START))
            echo "  ✓ Scanned $CLAMAV_FILES_SCANNED files"
            echo "  ⏱️  Duration: ${DURATION}s"
            echo ""
            echo "✓ ClamAV scan complete - Found: $CLAM_INFECTED | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE"
            log_message "ClamAV: Scan complete - $CLAM_INFECTED infected files in ${DURATION}s"
            ;;

        maldet)
            SCAN_START=$(date +%s)
            log_message "Maldet: Updating signatures"

            if ! maldet -u &>> "$LOG_DIR/maldet.log"; then
                log_message "WARNING: Maldet signature update failed (continuing with existing signatures)"
                echo "⚠️  WARNING: Signature update failed, using existing signatures"
            fi

            log_message "Maldet: Starting scan with live progress"
            echo ""
            echo "  📁 Scanning path(s): ${SCAN_PATHS[*]}"
            echo "  ⏳ Scanner: Maldet/LMD (Linux-specific malware detection...)"
            echo ""

            # Scan each path individually with -a (scan-all) flag
            # Note: -a flag scans all files regardless of modification time
            # Cannot combine -a with -f (file-list), so we loop through paths
            MALDET_EXIT=0
            MALDET_PIDS=()

            for path in "${SCAN_PATHS[@]}"; do
                if [ ! -d "$path" ]; then
                    log_message "Maldet: Skipping non-existent path: $path"
                    continue
                fi

                log_message "Maldet: Scanning $path with -a (all files)"

                # Run with -a (scan-all) for comprehensive scanning
                # Timeout after 2 hours per path, run in background for better progress tracking
                timeout 7200 maldet -b -a "$path" &>> "$LOG_DIR/maldet.log" &
                MALDET_PIDS+=($!)

                # Give scan a moment to start
                sleep 1
            done

            # Wait for all maldet scans to complete and collect exit codes
            for pid in "${MALDET_PIDS[@]}"; do
                # Validate PID is numeric and non-zero before checking process
                if [ -n "$pid" ] && [ "$pid" -gt 0 ] && kill -0 "$pid" 2>/dev/null; then
                    wait "$pid"
                    exit_code=$?
                    if [ "$exit_code" -ne 0 ]; then
                        MALDET_EXIT=$exit_code
                    fi
                fi
            done

            echo "" # New line after progress

            if [ "$MALDET_EXIT" -eq 124 ]; then
                log_message "ERROR: Maldet scan timed out after 2 hours"
                echo "  ⏱️  Scan timed out (exceeded 2 hour limit)"
                echo "Maldet scan timed out" >> "$SUMMARY_FILE"
                SCAN_END=$(date +%s)
                DURATION=$((SCAN_END - SCAN_START))
                echo ""
                continue
            elif [ "$MALDET_EXIT" -ne 0 ]; then
                log_message "ERROR: Maldet scan failed with exit code $MALDET_EXIT"
                echo "  ✗ Scan failed (exit code: $MALDET_EXIT) - check logs"
                echo "Maldet scan failed (exit code: $MALDET_EXIT)" >> "$SUMMARY_FILE"
                SCAN_END=$(date +%s)
                DURATION=$((SCAN_END - SCAN_START))
                echo ""
                continue
            fi

            # Extract scan results from event log (more reliable than parsing output)
            # Maldet logs to /usr/local/maldetect/logs/event_log
            # Use dynamic path search for portability across all platforms (FIXED Issue 2: comprehensive path discovery)
            local event_log=""

            # Search standard locations in order of likelihood
            for search_path in \
                "/usr/local/maldetect/logs/event_log" \
                "/opt/maldetect/logs/event_log" \
                "/var/log/maldetect/event_log" \
                "/var/lib/maldetect/logs/event_log"; do
                if [ -f "$search_path" ]; then
                    event_log="$search_path"
                    break
                fi
            done

            # Fallback: Search entire filesystem for event_log if standard paths not found
            if [ -z "$event_log" ] || [ ! -f "$event_log" ]; then
                event_log=$(find /usr/local/maldetect -name "event_log" -type f 2>/dev/null | head -1)
            fi
            if [ -z "$event_log" ] || [ ! -f "$event_log" ]; then
                event_log=$(find /opt -name "event_log" -type f 2>/dev/null | head -1)
            fi
            if [ -z "$event_log" ] || [ ! -f "$event_log" ]; then
                event_log=$(find /var -name "event_log" -type f 2>/dev/null | head -1)
            fi

            MALDET_FILES_SCANNED="0"
            MALDET_HITS="0"

            if [ -f "$event_log" ]; then
                # Use -E instead of -P for portability (BSD grep doesn't support -P)
                # FIXED Issue 2A: Robust parsing independent of format variations
                last_line=$(grep "scan completed" "$event_log" 2>/dev/null | tail -1)
                MALDET_FILES_SCANNED=$(echo "$last_line" | grep -oE '[0-9]+ files' 2>/dev/null | grep -oE '^[0-9]+' || echo "0")
                MALDET_HITS=$(echo "$last_line" | grep -oE '[0-9]+ (malware hits|malicious)' 2>/dev/null | grep -oE '^[0-9]+' || echo "0")
            fi

            # Validate numbers
            if ! [[ "$MALDET_FILES_SCANNED" =~ ^[0-9]+$ ]]; then
                MALDET_FILES_SCANNED=0
            fi
            if ! [[ "$MALDET_HITS" =~ ^[0-9]+$ ]]; then
                MALDET_HITS=0
            fi

            SCAN_END=$(date +%s)
            DURATION=$((SCAN_END - SCAN_START))
            echo "  ✓ Scanned $MALDET_FILES_SCANNED files"
            echo "  ⏱️  Duration: ${DURATION}s"
            echo ""
            echo "✓ Maldet scan complete - Found: ${MALDET_HITS:-0} | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE"
            log_message "Maldet: Scan complete - ${MALDET_HITS:-0} hits in ${DURATION}s"
            ;;

        rkhunter)
            SCAN_START=$(date +%s)
            log_message "RKHunter: Updating definitions"

            if ! rkhunter --update &>> "$LOG_DIR/rkhunter.log"; then
                log_message "WARNING: RKHunter update failed (continuing with existing definitions)"
                echo "⚠️  WARNING: Definition update failed, using existing definitions"
            fi

            log_message "RKHunter: Starting scan with live test display"
            echo ""
            echo "  🔍 System scan: Checking for rootkits, backdoors, exploits"
            echo "  ⏳ Scanner: Rootkit Hunter (system-wide integrity check...)"
            echo ""

            # Run with timeout (30 minutes, RKHunter is usually fast)
            # Show test names as they run
            # FIXED Issue 3A: Capture output to variable FIRST to avoid subshell exit code loss
            output=$(timeout 1800 rkhunter --check --skip-keypress --report-warnings-only 2>&1)
            RKH_EXIT=$?

            # Log output and display progress (using process substitution to avoid subshell issues)
            while IFS= read -r line; do
                # Parse test names: "Checking for..." or "Testing..."
                if [[ "$line" =~ ^Checking\ for\ (.+)$ ]] || [[ "$line" =~ ^Testing\ (.+)$ ]]; then
                    test_name="${BASH_REMATCH[1]:-}"
                    [ -n "$test_name" ] && printf "\r  → %-60s" "${test_name:0:60}"
                elif [[ "$line" =~ ^Scanning\ (.+)$ ]]; then
                    scan_item="${BASH_REMATCH[1]:-}"
                    [ -n "$scan_item" ] && printf "\r  → Scanning: %-50s" "${scan_item:0:50}"
                fi
            done < <(echo "$output" | tee -a "$LOG_DIR/rkhunter.log")
            echo ""  # New line after test display

            if [ "$RKH_EXIT" -eq 124 ]; then
                log_message "ERROR: RKHunter scan timed out after 30 minutes"
                echo "  ⏱️  Scan timed out (exceeded 30 minute limit)"
                echo "RKHunter scan timed out" >> "$SUMMARY_FILE"
                SCAN_END=$(date +%s)
                DURATION=$((SCAN_END - SCAN_START))
                echo ""
                continue
            elif [ "$RKH_EXIT" -gt 1 ] && [ "$RKH_EXIT" -ne 127 ]; then
                log_message "WARNING: RKHunter scan completed with exit code $RKH_EXIT"
                echo "  ⚠️  Scan completed with warnings (exit code: $RKH_EXIT)"
            fi

            # Extract warnings (FIXED Issue 3B: add numeric validation)
            RKH_WARNINGS=$(grep -c "Warning:" "$LOG_DIR/rkhunter.log" 2>/dev/null) || RKH_WARNINGS=0
            if ! [[ "$RKH_WARNINGS" =~ ^[0-9]+$ ]]; then
                RKH_WARNINGS=0
            fi

            # Extract any rootkits found (search for rootkit entries with found status)
            grep "Rootkit" "$LOG_DIR/rkhunter.log" 2>/dev/null | grep -i "found" >> "$INFECTED_LIST" 2>/dev/null || true

            SCAN_END=$(date +%s)
            DURATION=$((SCAN_END - SCAN_START))
            echo "  ✓ System integrity check complete"
            echo "  ⏱️  Duration: ${DURATION}s"
            echo ""
            echo "✓ RKHunter scan complete - Warnings: $RKH_WARNINGS | Duration: ${DURATION}s" | tee -a "$SUMMARY_FILE"
            log_message "RKHunter: Scan complete - $RKH_WARNINGS warnings in ${DURATION}s"
            ;;
    esac

    echo "" | tee -a "$SUMMARY_FILE"
    SCANNERS_COMPLETED=$((SCANNERS_COMPLETED + 1))

    # Wait between scanners
    if [ "${SCANNERS_COMPLETED:-0}" -lt "$TOTAL_SCANNERS" ]; then
        echo "Waiting 3 seconds before next scanner..."
        sleep 3
    fi
done

# Finalize report with consolidated summary
{
    echo "=========================================="
    echo "Scan Session Complete"
    echo "Completed: $(date)"
    echo "=========================================="
    echo ""

    # Consolidated Scanner Results Table
    echo "SCANNER RESULTS SUMMARY:"
    echo "────────────────────────────────────────"

    # ImunifyAV results
    if echo "${available_scanners[*]}" | grep -q "imunify" || true; then
        IMUNIFY_COUNT=$(grep -o "ImunifyAV scan complete - Found: [0-9]*" "$SUMMARY_FILE" | grep -o "[0-9]*$" || echo "N/A")
        printf "%-20s %s\n" "ImunifyAV:" "$IMUNIFY_COUNT threats detected"
    fi

    # ClamAV results
    if echo "${available_scanners[*]}" | grep -q "clamav" || true; then
        CLAM_COUNT=$(grep -o "ClamAV scan complete - Found: [0-9]*" "$SUMMARY_FILE" | grep -o "[0-9]*$" || echo "N/A")
        printf "%-20s %s\n" "ClamAV:" "$CLAM_COUNT infected files"
    fi

    # Maldet results
    if echo "${available_scanners[*]}" | grep -q "maldet" || true; then
        printf "%-20s %s\n" "Maldet:" "Scan complete (check logs)"
    fi

    # RKHunter results
    if echo "${available_scanners[*]}" | grep -q "rkhunter" || true; then
        RKH_COUNT=$(grep -o "RKHunter scan complete - Warnings: [0-9]*" "$SUMMARY_FILE" | grep -o "[0-9]*$" || echo "N/A")
        printf "%-20s %s\n" "Rootkit Hunter:" "$RKH_COUNT warnings"
    fi

    echo "────────────────────────────────────────"
    echo ""

    if [ -f "$INFECTED_LIST" ] && [ -s "$INFECTED_LIST" ]; then
        echo "⚠️  INFECTED FILES DETECTED:"
        echo ""
        sort -u "$INFECTED_LIST"
        echo ""
        echo "ACTION REQUIRED: Review and quarantine/remove infected files"
        echo ""

        # IP Reputation Integration: Feature temporarily disabled
        # TODO: IP flagging feature requires refactoring to fix subshell scope issues and undefined function dependencies
        # See audit report: CRITICAL-2, CRITICAL-3 for detailed findings
        # This feature will be re-enabled in a future update with proper implementation
        #
        # Disabled functionality:
        # - Would correlate infected files with Apache logs to find uploading IPs
        # - Would flag malicious IPs in reputation database
        # - Requires flag_ip_attack() function import and subshell scope fixes

        echo ""
    else
        echo "✓ No infected files detected by automated scan."
        echo ""
        echo "Review individual scanner logs for detailed information:"
        echo "  • ImunifyAV: $LOG_DIR/imunify.log"
        echo "  • ClamAV: $LOG_DIR/clamav.log"
        echo "  • Maldet: $LOG_DIR/maldet.log"
        echo "  • RKHunter: $LOG_DIR/rkhunter.log"
    fi
} >> "$SUMMARY_FILE"

# Validate scan results
log_message "Validating scan results..."
validation_issues=0

# Check that each scanner produced output
for scanner in "${available_scanners[@]}"; do
    case "$scanner" in
        imunify)
            if [ ! -s "$LOG_DIR/imunify.log" ]; then
                log_message "WARNING: ImunifyAV log file is empty or missing"
                echo "⚠️  WARNING: ImunifyAV scan may not have completed properly" >> "$SUMMARY_FILE"
                validation_issues=$((validation_issues + 1))
            fi
            ;;
        clamav)
            if [ ! -s "$LOG_DIR/clamav.log" ]; then
                log_message "WARNING: ClamAV log file is empty or missing"
                echo "⚠️  WARNING: ClamAV scan may not have completed properly" >> "$SUMMARY_FILE"
                validation_issues=$((validation_issues + 1))
            else
                # Verify ClamAV reached the summary line
                if ! grep -q "Scanned files:" "$LOG_DIR/clamav.log"; then
                    log_message "WARNING: ClamAV scan may have been interrupted (no summary found)"
                    echo "⚠️  WARNING: ClamAV scan may have been interrupted" >> "$SUMMARY_FILE"
                    validation_issues=$((validation_issues + 1))
                fi
            fi
            ;;
        maldet)
            if [ ! -s "$LOG_DIR/maldet.log" ]; then
                log_message "WARNING: Maldet log file is empty or missing"
                echo "⚠️  WARNING: Maldet scan may not have completed properly" >> "$SUMMARY_FILE"
                validation_issues=$((validation_issues + 1))
            fi
            ;;
        rkhunter)
            if [ ! -s "$LOG_DIR/rkhunter.log" ]; then
                log_message "WARNING: RKHunter log file is empty or missing"
                echo "⚠️  WARNING: RKHunter scan may not have completed properly" >> "$SUMMARY_FILE"
                validation_issues=$((validation_issues + 1))
            fi
            ;;
    esac
done

if [ $validation_issues -eq 0 ]; then
    log_message "All scans completed successfully - validation passed"
    echo "" >> "$SUMMARY_FILE"
    echo "✓ Scan Validation: All scanners completed successfully" >> "$SUMMARY_FILE"
else
    log_message "WARNING: $validation_issues validation issue(s) found - review logs carefully"
    echo "" >> "$SUMMARY_FILE"
    echo "⚠️  Scan Validation: $validation_issues issue(s) found - review logs" >> "$SUMMARY_FILE"
fi

# Generate client report automatically (inline to work in standalone scripts)
log_message "Generating client-facing security report"

# Check if function exists, if not generate inline
if declare -f generate_client_report > /dev/null 2>&1; then
    generate_client_report "$SCAN_DIR" > /dev/null 2>&1
else
    # Inline client report generation for standalone scripts
    client_report_file="$RESULTS_DIR/client_report.txt"

    # Extract scan info (using safe delimiters to avoid injection)
    scan_date=$(grep "Started:" "$SUMMARY_FILE" | head -1 | sed 's|Started: ||' || echo "Unknown")
    scan_paths=$(sed -n '/^Paths:/,/^$/p' "$SUMMARY_FILE" | tail -n +2 | grep -v "^$" | tr '\n' ', ' | sed 's|, $||' || echo "$SYS_USER_HOME_BASE")

    # Analyze infected files for false positives
    real_threats_count=0
    false_positives_list=""
    real_threats_list=""

    if [ -f "$RESULTS_DIR/infected_files.txt" ] && [ -s "$RESULTS_DIR/infected_files.txt" ]; then
        while IFS= read -r file; do
            if [[ "$file" =~ /logs?/.*\.(log|gz|bz2)$ ]] || \
               [[ "$file" =~ /awstats/ ]] || \
               [[ "$file" =~ /tmp/.*\.txt$ ]] || \
               [[ "$file" =~ \.log\.[0-9]+$ ]]; then
                false_positives_list="${false_positives_list}  • $file"$'\n'
            else
                real_threats_list="${real_threats_list}📁 $file"$'\n'
                real_threats_count=$((real_threats_count + 1))
            fi
        done < "$RESULTS_DIR/infected_files.txt"
    fi

    # Generate report
    {
        echo "MALWARE SCAN REPORT - $scan_date"
        echo "═══════════════════════════════════════════════════════════"
        echo ""
        echo "Scanned with: ImunifyAV, ClamAV, Linux Maldet, RKHunter"
        echo ""

        if [ "$real_threats_count" -eq 0 ]; then
            echo "RESULT: ✅ No malware found - your server is clean"
        else
            echo "RESULT: ⚠️  $real_threats_count infected file(s) detected"
            echo ""
            echo "INFECTED FILES:"
            echo "$real_threats_list"
            echo "NEXT STEPS:"
            echo "  1. Remove infected files immediately"
            echo "  2. Change all passwords"
            echo "  3. Update WordPress/plugins to latest versions"
        fi

        if [ -n "$false_positives_list" ]; then
            echo ""
            echo "───────────────────────────────────────────────────────────"
            echo "NOTE: Attack attempts were detected in your server logs."
            echo "These were successfully blocked. No action needed."
        fi

        echo ""
        echo "Scan ID: ${SCAN_DIR##*/}"
    } > "$client_report_file"
fi

# Display completion
clear
echo "=========================================="
echo -e "${GREEN}Malware Scan Complete!${NC}"
echo "=========================================="
echo "Session: ${SCAN_DIR##*/}"
echo "Completed: $(date)"
echo ""
echo "Results saved to:"
echo "  Summary: $SUMMARY_FILE"
echo "  Logs: $LOG_DIR/"
echo ""
echo -e "${CYAN}Client Report (copy/paste for tickets):${NC}"
echo "  $RESULTS_DIR/client_report.txt"
echo ""

# Show summary
cat "$SUMMARY_FILE"

echo ""
echo "=========================================="
echo ""
echo -e "${CYAN}TIP:${NC} To view the client-friendly report:"
echo "  cat $RESULTS_DIR/client_report.txt"
echo ""

# Prompt for cleanup (RKHunter cleanup handled by trap)
echo ""
if confirm "Delete scan script? (Logs and results will be preserved)"; then
    log_message "User requested cleanup - deleting scan script"
    echo ""
    echo "Removing scan script..."
    rm -f "$SCAN_DIR/scan.sh"
    echo -e "${GREEN}✓ Scan script deleted${NC}"
    echo ""
    echo "Results preserved at: $SCAN_DIR"
    echo ""
else
    log_message "User chose to keep scan script"
fi

echo "Scan script and results preserved at: $SCAN_DIR"
echo ""

echo "You can:"
echo "  • Review logs: ls $LOG_DIR"
echo "  • View summary: cat $SUMMARY_FILE"
if [ -n "$SCAN_DIR" ] && [[ "$SCAN_DIR" != "/" ]]; then
    echo "  • Delete scan directory manually: rm -rf \"$SCAN_DIR\""
fi
echo ""
echo "Press Ctrl+A then D to detach from this screen session,"
echo "or press Enter to open an interactive shell in this session..."
echo ""
read -t 30 -p "" </dev/tty 2>/dev/null || true

# Keep screen session alive with an interactive shell
echo ""
echo "Opening interactive shell. Type 'exit' to close this screen session."
echo ""

log_message "Scan session ended - opening interactive shell"
exec bash
STANDALONE_EOF

    # Replace placeholder with actual paths
    paths_declaration="SCAN_PATHS=("
    for path in "${scan_paths[@]}"; do
        paths_declaration+="\"$path\" "
    done
    paths_declaration+=")"

    # Escape special characters for sed (handle \, /, &, |, $)
    # CRITICAL FIX: Must escape backslash first, then other special chars
    escaped_paths=$(printf '%s\n' "$paths_declaration" | sed -e 's/\\/\\\\/g; s/[\/&|]/\\&/g')

    if ! sed -i "s|PLACEHOLDER_SCAN_PATHS|$escaped_paths|" "$session_dir/scan.sh"; then
        echo -e "${RED}ERROR: Failed to generate standalone scanner script${NC}"
        return 1
    fi

    # Inject MALDET_ONLY flag for Maldet-dedicated scans
    local maldet_flag="${MALDET_ONLY:-0}"
    if ! sed -i "s|PLACEHOLDER_MALDET_ONLY|$maldet_flag|" "$session_dir/scan.sh"; then
        echo -e "${RED}ERROR: Failed to inject MALDET_ONLY flag${NC}"
        return 1
    fi

    # Make executable
    chmod +x "$session_dir/scan.sh"

    # Check if screen is installed
    if ! command -v screen &>/dev/null; then
        echo -e "${YELLOW}Warning: 'screen' not installed${NC}"
        echo ""
        echo "Screen allows you to detach from the scan session."
        echo ""
        echo "Options:"
        echo "  1. Auto-install screen (recommended)"
        echo "  2. Use nohup fallback (run in background without screen)"
        echo "  3. Cancel"
        echo ""
        read -p "Select option: " screen_option

        case "$screen_option" in
            1)
                echo ""
                echo "Installing screen..."
                if command -v yum &>/dev/null; then
                    yum install -y screen
                elif command -v apt-get &>/dev/null; then
                    apt-get update && apt-get install -y screen
                else
                    echo -e "${RED}Unable to auto-install. Install manually: yum install screen${NC}"
                    read -p "Press Enter to continue..."
                    return 1
                fi

                if ! command -v screen &>/dev/null; then
                    echo -e "${RED}Installation failed${NC}"
                    read -p "Press Enter to continue..."
                    return 1
                fi

                echo -e "${GREEN}✓ Screen installed successfully${NC}"
                echo ""
                ;;
            2)
                # Use nohup fallback
                echo ""
                echo "Launching scan with nohup (background mode)..."
                nohup bash "$session_dir/scan.sh" > "$session_dir/logs/nohup.out" 2>&1 &
                scan_pid=$!

                sleep 1

                if ps -p "$scan_pid" > /dev/null 2>&1; then
                    echo ""
                    echo -e "${GREEN}✓ Standalone scanner started successfully!${NC}"
                    echo ""
                    echo "Session ID: $session_id"
                    echo "Process ID: $scan_pid"
                    echo "Results directory: $session_dir/results/"
                    echo ""
                    echo -e "${CYAN}Monitor the scan:${NC}"
                    echo "  tail -f $session_dir/logs/session.log"
                    echo ""
                    echo -e "${CYAN}Check if still running:${NC}"
                    echo "  ps -p \"$scan_pid\""
                    echo ""
                    echo -e "${GREEN}You can now safely delete the toolkit.${NC}"
                    echo -e "${GREEN}The scan will continue running independently.${NC}"
                    echo ""

                    # Store session info in reference database
                    store_reference "malware_standalone_latest" "$session_id"
                    store_reference "malware_standalone_${session_id}_dir" "$session_dir"
                    store_reference "malware_standalone_${session_id}_pid" "$scan_pid"

                    read -p "Press Enter to continue..."
                    return 0
                else
                    echo -e "${RED}Failed to start scan${NC}"
                    echo "Run manually: bash $session_dir/scan.sh"
                    read -p "Press Enter to continue..."
                    return 1
                fi
                ;;
            3)
                echo "Cancelled."
                read -p "Press Enter to continue..."
                return 0
                ;;
            *)
                echo -e "${RED}Invalid option${NC}"
                read -p "Press Enter to continue..."
                return 1
                ;;
        esac
    fi

    # Launch in screen session
    echo "Launching scan in screen session..."
    screen -dmS "$session_id" bash "$session_dir/scan.sh"

    sleep 1

    # Verify screen started (FIXED: use -F flag for literal matching)
    if screen -list | grep -qF "$session_id" || true; then
        echo ""
        echo -e "${GREEN}✓ Standalone scanner started successfully!${NC}"
        echo ""
        echo "Session ID: $session_id"
        echo "Screen session: $session_id"
        echo "Results directory: $session_dir/results/"
        echo ""
        echo -e "${CYAN}Monitor the scan:${NC}"
        echo "  screen -r $session_id"
        echo ""
        echo -e "${CYAN}Check progress:${NC}"
        echo "  tail -f $session_dir/logs/session.log"
        echo ""
        echo -e "${CYAN}Detach from screen:${NC}"
        echo "  Press: Ctrl+A then D"
        echo ""
        echo -e "${GREEN}You can now safely delete the toolkit.${NC}"
        echo -e "${GREEN}The scan will continue running independently.${NC}"
        echo ""

        # Store session info in reference database
        store_reference "malware_standalone_latest" "$session_id"
        store_reference "malware_standalone_${session_id}_dir" "$session_dir"

    else
        echo -e "${RED}Failed to start screen session${NC}"
        echo "Run manually: bash $session_dir/scan.sh"
    fi

    read -p "Press Enter to continue..."
}

# Compare results from multiple scanners
compare_scan_results() {
    echo ""
    print_header "Compare Scanner Results"

    # Get latest multiscan session
    local latest_session=$(get_reference "malware_multiscan_latest")

    if [ -z "$latest_session" ]; then
        echo "No multi-scanner sessions found."
        echo ""
        echo "Run a scan with 'All Available Scanners' option first."
        read -p "Press Enter to continue..."
        return
    fi

    local report_file=$(get_reference "malware_multiscan_${latest_session}")

    if [ -f "$report_file" ]; then
        echo "Latest multi-scanner session: $latest_session"
        echo ""
        less "$report_file"
    else
        echo "Report file not found: $report_file"
    fi

    echo ""
    read -p "Press Enter to continue..."
}

# Launch standalone scanner menu
launch_standalone_scanner_menu() {
    local preset_scope="$1"  # Optional: server, user, domain, custom

    echo ""
    print_header "Launch Standalone Scanner"

    echo "This will create a self-contained scanner in /opt/ that runs"
    echo "independently. You can safely delete the toolkit after launching."
    echo ""

    if ! detect_control_panel; then
        read -p "Press Enter to continue..."
        return 1
    fi

    # Validate that docroots were found
    if [ ${#sanitized_docroot[@]} -eq 0 ]; then
        echo -e "${YELLOW}WARNING: No docroots found on this system${NC}"
        echo "You can still:"
        echo "  1. Scan specific paths manually (custom path option)"
        echo "  2. Scan from root (entire server)"
        echo ""
    fi

    echo "Control Panel: ${CONTROL_PANEL^}"
    echo "Available Scanners: ${available_scanners[@]}"
    echo ""

    local scope_choice
    local scan_paths=()
    local scan_description=""

    # If preset scope provided, use it; otherwise show menu
    if [ -n "$preset_scope" ]; then
        case "$preset_scope" in
            server) scope_choice=1 ;;
            all_users) scope_choice=2 ;;
            user) scope_choice=3 ;;
            domain) scope_choice=4 ;;
            custom) scope_choice=5 ;;
            *) scope_choice=0 ;;
        esac
    else
        echo "Select scan scope:"
        echo "  1. Entire server (scan from / - WARNING: may take several hours)"
        echo "  2. Specific user account"
        echo "  3. Specific domain"
        echo "  4. Custom path"
        echo "  0. Cancel"
        echo ""
        read -p "Select option: " scope_choice
    fi

    case $scope_choice in
        1)
            # Entire server
            scan_paths=("/")
            scan_description="full server scan"

            echo ""
            echo -e "${YELLOW}WARNING: Full server scan from /${NC}"
            echo "This will scan the ENTIRE filesystem including:"
            echo "  • All user directories"
            echo "  • System files"
            echo "  • Application files"
            echo ""
            echo "This scan may take several hours and use significant resources."
            echo ""
            read -p "Are you sure you want to proceed? (yes/no): " confirm_full_scan

            if [ "$confirm_full_scan" != "yes" ]; then
                echo "Cancelled."
                read -p "Press Enter to continue..."
                return 0
            fi

            echo ""
            echo "Scan scope: Entire server from /"
            ;;

        2)
            # All user accounts
            echo ""
            echo "Scanning all user home directories..."

            # Determine user directories based on control panel
            # Each panel has different home directory structures
            scan_paths=()
            case "$CONTROL_PANEL" in
                plesk)
                    # Plesk: /var/www/vhosts/username/ (exclude 'system' subdirectory)
                    # Find all user vhosts (skip 'system' which contains configs)
                    while IFS= read -r vhost_dir; do
                        [ -n "$vhost_dir" ] && [ -d "$vhost_dir" ] && scan_paths+=("$vhost_dir")
                    done < <(find /var/www/vhosts -maxdepth 1 -type d -name "[a-zA-Z0-9]*" ! -name "system" ! -name "." 2>/dev/null | sort)
                    scan_description="all Plesk user vhosts (excluding system configs)"
                    ;;
                cpanel)
                    # cPanel: /home/username/ (standard)
                    while IFS= read -r home_dir; do
                        [ -n "$home_dir" ] && [ -d "$home_dir" ] && scan_paths+=("$home_dir")
                    done < <(find /home -maxdepth 1 -type d ! -name "." ! -name ".." ! -name "lost+found" 2>/dev/null | sort)
                    scan_description="all cPanel user home directories"
                    ;;
                interworx)
                    # InterWorx: /home/username/domain.com/html
                    # Can also scan /home/username for all user content
                    while IFS= read -r user_dir; do
                        [ -n "$user_dir" ] && [ -d "$user_dir" ] && scan_paths+=("$user_dir")
                    done < <(find /home -maxdepth 1 -type d ! -name "." ! -name ".." 2>/dev/null | sort)
                    scan_description="all InterWorx user directories"
                    ;;
                *)
                    # Standalone: /home/username/
                    while IFS= read -r home_dir; do
                        [ -n "$home_dir" ] && [ -d "$home_dir" ] && scan_paths+=("$home_dir")
                    done < <(find /home -maxdepth 1 -type d ! -name "." ! -name ".." ! -name "lost+found" 2>/dev/null | sort)
                    scan_description="all user home directories"
                    ;;
            esac

            # Check if any paths were found
            if [ ${#scan_paths[@]} -eq 0 ]; then
                echo -e "${YELLOW}Warning: No user directories found${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            echo "Control Panel: ${CONTROL_PANEL^}"
            echo "User directories found: ${#scan_paths[@]}"
            echo "Scan scope: $scan_description"
            ;;

        3)
            # Specific user
            echo ""
            echo "Available users:"
            select_user_interactive "Select user account to scan"

            if [ -z "$SELECTED_USER" ]; then
                echo "No user selected."
                read -p "Press Enter to continue..."
                return 1
            fi

            # Get user's docroots (FIXED: more specific path matching to avoid false matches like 'test' matching 'username_test')
            for docroot in "${sanitized_docroot[@]}"; do
                # Match patterns: /home/username/ or /var/www/vhosts/username/ or /chroot/home/username/
                if [[ "$docroot" == */home/$SELECTED_USER/* ]] || [[ "$docroot" == */vhosts/$SELECTED_USER/* ]] || [[ "$docroot" == */chroot/home/$SELECTED_USER/* ]]; then
                    scan_paths+=("$docroot")
                fi
            done

            if [ ${#scan_paths[@]} -eq 0 ]; then
                echo -e "${RED}No docroots found for user: $SELECTED_USER${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            scan_description="user $SELECTED_USER"
            echo "Found ${#scan_paths[@]} docroots for $SELECTED_USER"
            ;;

        4)
            # Specific domain
            echo ""
            read -p "Enter domain name: " domain

            if [ -z "$domain" ]; then
                echo "No domain entered."
                read -p "Press Enter to continue..."
                return 1
            fi

            # Find docroot for domain (FIXED: more specific matching to distinguish 'example' from 'example-prod' or 'prefix_example')
            for docroot in "${sanitized_docroot[@]}"; do
                # Match patterns: domain.com/html or domain.com/public_html or /domain.com/httpdocs
                if [[ "$docroot" == *"/$domain/"* ]] || [[ "$docroot" == *"/$domain"* ]]; then
                    scan_paths+=("$docroot")
                fi
            done

            if [ ${#scan_paths[@]} -eq 0 ]; then
                echo -e "${RED}No docroot found for domain: $domain${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            scan_description="domain $domain"
            echo "Found docroot: ${scan_paths[0]}"
            ;;

        5)
            # Custom path
            echo ""
            read -p "Enter path to scan: " custom_path

            if [ -z "$custom_path" ]; then
                echo "No path entered."
                read -p "Press Enter to continue..."
                return 1
            fi

            if [ ! -d "$custom_path" ]; then
                echo -e "${RED}Path does not exist: $custom_path${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            scan_paths=("$custom_path")
            scan_description="custom path $custom_path"
            ;;

        0)
            return 0
            ;;

        *)
            echo -e "${RED}Invalid option${NC}"
            sleep 1
            return 1
            ;;
    esac

    # Confirm before generating
    echo ""
    echo -e "${YELLOW}Ready to generate standalone scanner${NC}"
    echo "Scope: $scan_description"
    echo "Paths: ${#scan_paths[@]}"
    echo "Scanners: ${available_scanners[@]}"
    echo ""
    read -p "Generate and launch? (yes/no): " confirm

    if [ "$confirm" != "yes" ]; then
        echo "Cancelled."
        read -p "Press Enter to continue..."
        return 0
    fi

    # Generate and launch standalone scanner
    generate_standalone_scanner "${scan_paths[@]}"
}

# Check status of all standalone scanners
check_standalone_status() {
    echo ""
    print_header "Standalone Scanner Status"

    # Find all malware-* directories in /opt (proper array initialization to handle spaces in names)
    if [ ! -d /opt ]; then
        echo "ERROR: /opt directory not found or not accessible"
        read -p "Press Enter to continue..."
        return 1
    fi

    local standalone_dirs=()
    while IFS= read -r dir; do
        [ -n "$dir" ] && standalone_dirs+=("$dir")
    done < <(find /opt -maxdepth 1 -type d -name "malware-*" 2>/dev/null | sort -r)

    if [ ${#standalone_dirs[@]} -eq 0 ]; then
        echo "No standalone scanner sessions found."
        echo ""
        read -p "Press Enter to continue..."
        return 0
    fi

    echo "Active Sessions:"
    echo ""

    local running_count=0
    local completed_count=0
    local error_count=0

    for dir in "${standalone_dirs[@]}"; do
        local session_name=${dir##*/}

        # Check if still running by looking for bash process executing scan.sh
        # Use pgrep with exact match to avoid false positives from viewers/editors
        if pgrep -f "bash $dir/scan.sh" > /dev/null 2>&1 || [ -f "$dir/.scan_running" ]; then
            echo -e "  ${GREEN}●${NC} $session_name [RUNNING]"
            running_count=$((running_count + 1))

            # Show progress if available
            if [ -f "$dir/logs/session.log" ]; then
                local last_log=$(tail -1 "$dir/logs/session.log" 2>/dev/null)
                echo "     Latest: $last_log"
            fi
        elif [ -f "$dir/results/summary.txt" ]; then
            # Check if completed successfully
            if grep -q "Multi-Scanner Session Complete\|Scan session ended" "$dir/results/summary.txt" 2>/dev/null; then
                echo -e "  ${CYAN}✓${NC} $session_name [COMPLETED]"
                completed_count=$((completed_count + 1))

                # Show infected count if available
                if [ -f "$dir/results/infected_files.txt" ] && [ -s "$dir/results/infected_files.txt" ]; then
                    local infected_count=$(wc -l < "$dir/results/infected_files.txt")
                    echo -e "     Found: ${RED}$infected_count infected files${NC}"
                fi
            else
                echo -e "  ${RED}✗${NC} $session_name [ERROR/INCOMPLETE]"
                error_count=$((error_count + 1))
            fi
        else
            echo -e "  ${YELLOW}?${NC} $session_name [UNKNOWN - no results yet]"
        fi

        echo ""
    done

    echo "Summary:"
    echo "  Running: $running_count"
    echo "  Completed: $completed_count"
    echo "  Errors: $error_count"
    echo "  Total: ${#standalone_dirs[@]}"

    echo ""
    read -p "Press Enter to continue..."
}

# Delete standalone scanner sessions
delete_standalone_sessions() {
    echo ""
    print_header "Delete Standalone Scanner Sessions"

    # Find all malware-* directories in /opt (proper array initialization to handle spaces in names)
    if [ ! -d /opt ]; then
        echo "ERROR: /opt directory not found or not accessible"
        read -p "Press Enter to continue..."
        return 1
    fi

    local standalone_dirs=()
    while IFS= read -r dir; do
        [ -n "$dir" ] && standalone_dirs+=("$dir")
    done < <(find /opt -maxdepth 1 -type d -name "malware-*" 2>/dev/null | sort -r)

    if [ ${#standalone_dirs[@]} -eq 0 ]; then
        echo "No standalone scanner sessions found."
        echo ""
        read -p "Press Enter to continue..."
        return 0
    fi

    echo "Available sessions:"
    echo ""

    # List sessions with status
    local i=1
    for dir in "${standalone_dirs[@]}"; do
        local session_name=${dir##*/}
        local status="completed"

        if pgrep -f "bash $dir/scan.sh" > /dev/null 2>&1 || [ -f "$dir/.scan_running" ]; then
            status="${GREEN}running${NC}"
        fi

        echo -e "  $i. $session_name [$status]"
        i=$((i + 1))
    done

    echo ""
    echo "  A. Delete all completed sessions"
    echo "  0. Cancel"
    echo ""

    read -p "Select session to delete (or A for all completed): " delete_choice

    case "$delete_choice" in
        0)
            return 0
            ;;
        [Aa])
            # Delete all completed sessions
            echo ""
            local deleted=0
            for dir in "${standalone_dirs[@]}"; do
                if ! pgrep -f "$dir/scan.sh" > /dev/null 2>&1; then
                    echo "Deleting: ${dir##*/}"
                    rm -rf "$dir"
                    deleted=$((deleted + 1))
                fi
            done
            echo ""
            echo -e "${GREEN}✓ Deleted $deleted completed session(s)${NC}"
            ;;
        *)
            # Delete specific session
            # Validate numeric input
            if ! [[ "$delete_choice" =~ ^[0-9]+$ ]]; then
                echo -e "${RED}Invalid choice (must be a number)${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            if [ "$delete_choice" -lt 1 ] || [ "$delete_choice" -gt ${#standalone_dirs[@]} ]; then
                echo -e "${RED}Invalid choice (out of range)${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            local selected_dir="${standalone_dirs[$((delete_choice-1))]}"
            local session_name=${selected_dir##*/}

            # Check if running
            if pgrep -f "$selected_dir/scan.sh" > /dev/null 2>&1; then
                echo ""
                echo -e "${YELLOW}Warning: This scan is currently running!${NC}"
                read -p "Stop scan and delete? (yes/no): " confirm_running

                if [ "$confirm_running" = "yes" ]; then
                    pkill -f "$selected_dir/scan.sh"
                    sleep 1
                    rm -rf "$selected_dir"
                    echo -e "${GREEN}✓ Stopped and deleted: $session_name${NC}"
                else
                    echo "Cancelled."
                fi
            else
                echo ""
                read -p "Delete $session_name? (yes/no): " confirm_delete

                if [ "$confirm_delete" = "yes" ]; then
                    rm -rf "$selected_dir"
                    echo -e "${GREEN}✓ Deleted: $session_name${NC}"
                else
                    echo "Cancelled."
                fi
            fi
            ;;
    esac

    echo ""
    read -p "Press Enter to continue..."
}

# Main scan menu
# Maldet-specific scan menu (dedicated section for fastest scanner)
maldet_scan_submenu() {
    while true; do
        echo ""
        print_header "Maldet Scanner - Linux Malware Detection"
        echo "Fast, efficient, Linux-specific malware detection"
        echo ""

        # Show installation status (use cached check for performance)
        if is_scanner_cached "maldet"; then
            echo -e "${GREEN}✓ Status: Installed${NC}"
        else
            echo -e "${RED}✗ Status: NOT installed${NC}"
        fi
        echo ""

        echo "Select option:"
        echo -e "  ${CYAN}1.${NC} Scan entire server (fastest comprehensive scan)"
        echo -e "  ${CYAN}2.${NC} Scan all user accounts"
        echo -e "  ${CYAN}3.${NC} Scan specific user account"
        echo -e "  ${CYAN}4.${NC} Scan specific domain"
        echo -e "  ${CYAN}5.${NC} Scan custom path"
        echo ""
        echo -e "  ${CYAN}6.${NC} Update Maldet signatures"
        echo -e "  ${CYAN}7.${NC} View Maldet results"
        echo -e "  ${CYAN}8.${NC} Install Maldet"
        echo ""
        echo -e "  ${RED}0.${NC} Back to main menu"
        echo ""

        while true; do
            read -p "Select option (0-8): " choice

            if ! [[ "$choice" =~ ^[0-8]$ ]]; then
                echo -e "${RED}Invalid option${NC}"
                sleep 1
                continue
            fi

            case $choice in
                1) maldet_launch_scan "server"; break ;;
                2) maldet_launch_scan "all_users"; break ;;
                3) maldet_launch_scan "user"; break ;;
                4) maldet_launch_scan "domain"; break ;;
                5) maldet_launch_scan "custom"; break ;;
                6) maldet_update_signatures; break ;;
                7) maldet_view_results; break ;;
                8) install_maldet_only; break ;;
                0) return 0 ;;
            esac
        done
    done
}

# Launch Maldet-specific scan with different scope options
maldet_launch_scan() {
    local scope="$1"

    echo ""
    print_header "Launching Maldet Scan - $scope"

    # Check if Maldet is installed (use cached check for performance)
    if ! is_scanner_cached "maldet"; then
        echo -e "${RED}✗ Maldet is not installed${NC}"
        echo ""
        read -p "Install Maldet now? (yes/no): " install_choice
        if [ "$install_choice" = "yes" ]; then
            install_all_scanners
            maldet_scan_submenu
        fi
        return 1
    fi

    # Find Maldet binary
    local maldet_bin=$(command -v maldet || find /usr/local -name maldet -type f 2>/dev/null | head -1)
    if [ -z "$maldet_bin" ]; then
        echo -e "${RED}✗ Maldet binary not found${NC}"
        read -p "Press Enter to continue..."
        return 1
    fi

    echo ""
    echo "Creating Maldet-only scan session..."
    echo "Scope: $scope"
    echo ""

    # For now, launch via the existing scanner menu but only with Maldet
    # Store preference for Maldet-only scanning
    export MALDET_ONLY=1
    launch_standalone_scanner_menu "$scope"
    unset MALDET_ONLY
}

# Update Maldet signatures
maldet_update_signatures() {
    echo ""
    print_header "Updating Maldet Signatures"

    # Check if Maldet is installed (use cached check for performance)
    if ! is_scanner_cached "maldet"; then
        echo -e "${RED}✗ Maldet is not installed${NC}"
        echo ""
        read -p "Install Maldet now? (yes/no): " install_choice
        if [ "$install_choice" = "yes" ]; then
            install_all_scanners
        fi
        return 1
    fi

    local maldet_bin=$(command -v maldet || find /usr/local -name maldet -type f 2>/dev/null | head -1)

    if [ -z "$maldet_bin" ]; then
        echo -e "${RED}✗ Maldet binary not found${NC}"
        read -p "Press Enter to continue..."
        return 1
    fi

    echo "Updating Maldet malware signatures..."
    echo "(This may take a few moments)"
    echo ""

    if timeout 120 "$maldet_bin" -u 2>&1 | tee /tmp/maldet-update.log | grep -E "updated|completed|signatures" || true; then
        echo ""
        echo -e "${GREEN}✓ Signatures updated successfully${NC}"
    else
        echo ""
        echo -e "${YELLOW}⚠ Signature update may have completed (check output above)${NC}"
    fi

    echo ""
    read -p "Press Enter to continue..."
}

# View Maldet-specific results
maldet_view_results() {
    echo ""
    print_header "Maldet Scan Results"

    if ! is_scanner_cached "maldet"; then
        echo -e "${RED}✗ Maldet is not installed${NC}"
        echo ""
        read -p "Press Enter to continue..."
        return 1
    fi

    local maldet_bin=$(command -v maldet || find /usr/local -name maldet -type f 2>/dev/null | head -1)

    if [ -z "$maldet_bin" ]; then
        echo -e "${RED}✗ Maldet binary not found${NC}"
        read -p "Press Enter to continue..."
        return 1
    fi

    echo "Recent Maldet scans:"
    echo ""

    if "$maldet_bin" -l 2>/dev/null | head -20; then
        echo ""
    else
        echo "No Maldet scans found"
        echo ""
    fi

    read -p "Press Enter to continue..."
}

show_scan_menu() {
    # Ensure print_banner is available before calling it
    if ! declare -f "print_banner" &>/dev/null; then
        echo "ERROR: print_banner function not found" >&2
        return 1
    fi

    # Ensure reference database is fresh (only rebuild if > 1 hour old)
    if command -v db_ensure_fresh &>/dev/null; then
        db_ensure_fresh 2>/dev/null || true
        clear
    fi

    while true; do
        # Call print_banner - MUST succeed
        print_banner "Malware Scanner" || {
            echo "ERROR: print_banner failed" >&2
            return 1
        }

        echo "Available Scanners:"
        if [ ${#available_scanners[@]} -eq 0 ]; then
            echo "  (None currently installed)"
        else
            for scanner in "${available_scanners[@]}"; do
                echo "  • ${scanner^}"
            done
        fi
        echo ""

        echo -e "${CYAN}Maldet Scanner (Fast, Linux-focused):${NC}"
        echo -e "  ${CYAN}1.${NC} Maldet menu (dedicated scanner)"
        echo ""

        echo -e "${CYAN}Create New Scan (All Scanners):${NC}"
        echo -e "  ${CYAN}2.${NC} Scan entire server (ClamAV, Maldet, RKHunter)"
        echo -e "  ${CYAN}3.${NC} Scan all user accounts (All scanners - recommended)"
        echo -e "  ${CYAN}4.${NC} Scan specific user account (All scanners)"
        echo -e "  ${CYAN}5.${NC} Scan specific domain (All scanners)"
        echo -e "  ${CYAN}6.${NC} Scan custom path (All scanners)"
        echo ""
        echo -e "${CYAN}Monitor & Manage:${NC}"
        echo -e "  ${CYAN}7.${NC} Check scan status"
        echo -e "  ${CYAN}8.${NC} View scan results"
        echo -e "  ${CYAN}9.${NC} Delete scan sessions"
        echo ""
        echo -e "${CYAN}Configuration:${NC}"
        echo -e "  ${CYAN}10.${NC} Install Maldet (fast, Linux-specific)"
        echo -e "  ${CYAN}11.${NC} Install ClamAV (open source antivirus)"
        echo -e "  ${CYAN}12.${NC} Install RKHunter (rootkit detection)"
        echo -e "  ${CYAN}13.${NC} Install ALL scanners (recommended)"
        echo -e "  ${CYAN}14.${NC} Scanner settings"
        echo ""
        echo -e "  ${RED}0.${NC} Back"
        echo ""

        # Validate choice input with retry loop
        while true; do
            read -p "Select option (0-14): " choice

            if ! [[ "$choice" =~ ^([0-9]|1[0-4])$ ]]; then
                echo -e "${RED}Invalid option${NC}"
                sleep 1
                continue
            fi

            case $choice in
                1) maldet_scan_submenu; break ;;
                2) launch_standalone_scanner_menu "server"; break ;;
                3) launch_standalone_scanner_menu "all_users"; break ;;
                4) launch_standalone_scanner_menu "user"; break ;;
                5) launch_standalone_scanner_menu "domain"; break ;;
                6) launch_standalone_scanner_menu "custom"; break ;;
                7) check_standalone_status; break ;;
                8) view_scan_results; break ;;
                9) delete_standalone_sessions; break ;;
                10) install_maldet_only; break ;;
                11) install_clamav_only; break ;;
                12) install_rkhunter_only; break ;;
                13) install_all_scanners; break ;;
                14) scanner_settings; break ;;
                0) return 0 ;;
            esac
        done
    done
}

# View scan results
view_scan_results() {
    echo ""
    print_header "Scan Results"

    echo "Select results to view:"
    echo "  1. Toolkit scan results"
    echo "  2. Standalone scanner results (/opt)"
    echo "  0. Back"
    echo ""

    read -p "Option: " result_type

    case "$result_type" in
        1)
            # Toolkit scan results
            echo ""
            echo "Select scanner to view results:"
            local i=1
            for scanner in "${available_scanners[@]}"; do
                echo "  $i. ${scanner^}"
                i=$((i + 1))
            done
            echo ""

            read -p "Scanner: " scanner_choice

            # Validate numeric input
            if ! [[ "$scanner_choice" =~ ^[0-9]+$ ]]; then
                echo -e "${RED}Invalid choice (must be a number)${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            if [ "$scanner_choice" -lt 1 ] || [ "$scanner_choice" -gt ${#available_scanners[@]} ]; then
                echo -e "${RED}Invalid choice (out of range)${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            local selected_scanner="${available_scanners[$((scanner_choice-1))]}"

            echo ""

            case "$selected_scanner" in
                imunify)
                    echo "Recent ImunifyAV scans:"
                    imunify-antivirus malware on-demand list --since $(date --date="7 days ago" '+%s') 2>/dev/null || echo "No scans found"
                    ;;
                clamav)
                    echo "Recent ClamAV scans:"
                    find "$SCRIPT_DIR/logs/malware-scans" -name "clamav_*.log" -mtime -7 2>/dev/null | sort -r | head -5 || echo "No scans found"
                    ;;
                maldet)
                    echo "Recent Maldet scans:"
                    maldet -l 2>/dev/null || echo "No scans found"
                    ;;
            esac
            ;;

        2)
            # Standalone scanner results
            echo ""
            echo "Standalone scanner sessions:"
            echo ""

            # Find all malware-* directories in /opt
            local standalone_dirs=($(find /opt -maxdepth 1 -type d -name "malware-*" 2>/dev/null | sort -r))

            if [ ${#standalone_dirs[@]} -eq 0 ]; then
                echo "No standalone scanner sessions found in /opt"
                echo ""
                read -p "Press Enter to continue..."
                return 0
            fi

            # List sessions
            local i=1
            for dir in "${standalone_dirs[@]}"; do
                local session_name=${dir##*/}
                local scan_date=${session_name#malware-}

                # Check if still running
                local status="completed"
                if pgrep -f "$dir/scan.sh" > /dev/null 2>&1; then
                    status="running"
                fi

                echo "  $i. $session_name [$status]"
                i=$((i + 1))
            done
            echo ""

            read -p "Select session (or 0 to cancel): " session_choice

            # Validate numeric input
            if ! [[ "$session_choice" =~ ^[0-9]+$ ]]; then
                echo -e "${RED}Invalid choice (must be a number)${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            if [ "$session_choice" = "0" ]; then
                return 0
            fi

            if [ "$session_choice" -lt 1 ] || [ "$session_choice" -gt ${#standalone_dirs[@]} ]; then
                echo -e "${RED}Invalid choice (out of range)${NC}"
                read -p "Press Enter to continue..."
                return 1
            fi

            local selected_dir="${standalone_dirs[$((session_choice-1))]}"
            echo ""
            echo "Session: ${selected_dir##*/}"
            echo "Location: $selected_dir"
            echo ""

            # Show results
            if [ -f "$selected_dir/results/summary.txt" ]; then
                echo "=== Summary ==="
                cat "$selected_dir/results/summary.txt"
                echo ""
            else
                echo "Summary not yet available (scan may still be running)"
                echo ""
            fi

            # Show infected files if any
            if [ -f "$selected_dir/results/infected_files.txt" ] && [ -s "$selected_dir/results/infected_files.txt" ]; then
                echo "=== Infected Files ==="
                cat "$selected_dir/results/infected_files.txt"
                echo ""
            fi

            # Show recent log entries
            if [ -f "$selected_dir/logs/session.log" ]; then
                echo "=== Recent Log Entries ==="
                tail -20 "$selected_dir/logs/session.log"
                echo ""
            fi

            echo "View full logs:"
            echo "  tail -f $selected_dir/logs/session.log"
            echo ""

            # Offer to generate client report
            echo -e "${CYAN}Actions:${NC}"
            echo "  1. Generate client-facing security report"
            echo "  0. Back to menu"
            echo ""

            read -p "Select action (or press Enter to continue): " action_choice

            case "$action_choice" in
                1)
                    generate_client_report "$selected_dir"
                    ;;
                0|"")
                    # Continue
                    ;;
                *)
                    echo -e "${RED}Invalid option${NC}"
                    ;;
            esac
            ;;

        0)
            return 0
            ;;

        *)
            echo -e "${RED}Invalid option${NC}"
            ;;
    esac

    echo ""
    read -p "Press Enter to continue..."
}

# Scanner settings
scanner_settings() {
    echo ""
    print_header "Scanner Settings"

    echo "Settings (placeholder for future enhancements):"
    echo "  • Auto-quarantine infected files"
    echo "  • Email notifications"
    echo "  • Scheduled scans"
    echo "  • Custom exclusions"
    echo ""
    echo "Coming soon..."

    read -p "Press Enter to continue..."
}

# Generate client-facing security report
generate_client_report() {
    local scan_dir="$1"

    if [ ! -d "$scan_dir" ]; then
        echo -e "${RED}Scan directory not found${NC}"
        return 1
    fi

    local summary_file="$scan_dir/results/summary.txt"
    local infected_file="$scan_dir/results/infected_files.txt"
    local clamav_log="$scan_dir/logs/clamav.log"
    local session_log="$scan_dir/logs/session.log"
    local report_file="$scan_dir/results/client_report.txt"

    if [ ! -f "$summary_file" ]; then
        echo -e "${RED}Summary file not found - scan may not be complete${NC}"
        return 1
    fi

    # Extract scan info
    local session_name=${scan_dir##*/}
    local scan_date=$(grep "Started:" "$summary_file" | head -1 | sed 's/Started: //' || echo "Unknown")
    local scan_paths=$(sed -n '/^Paths:/,/^$/p' "$summary_file" | tail -n +2 | grep -v "^$" | tr '\n' ', ' | sed 's/, $//' || echo "/")

    # Count threats
    local total_threats=0
    local imunify_count=$(grep -o "ImunifyAV:.*[0-9]* threats" "$summary_file" | grep -o "[0-9]*" || echo "0")
    local clamav_count=$(grep -o "ClamAV:.*[0-9]* infected" "$summary_file" | grep -o "[0-9]*" || echo "0")
    local maldet_hits=$(grep -o "Maldet:.*[0-9]* hits" "$summary_file" | grep -o "[0-9]*" || echo "0")

    # Calculate total (only real malware, not rootkit warnings)
    total_threats=$((imunify_count + clamav_count + maldet_hits))

    # Analyze infected files for false positives
    local real_threats=()
    local false_positives=()

    if [ -f "$infected_file" ] && [ -s "$infected_file" ]; then
        while IFS= read -r file; do
            # Check if likely false positive (logs, stats, cache)
            if [[ "$file" =~ /logs?/.*\.(log|gz|bz2)$ ]] || \
               [[ "$file" =~ /awstats/ ]] || \
               [[ "$file" =~ /tmp/.*\.txt$ ]] || \
               [[ "$file" =~ \.log\.[0-9]+$ ]]; then
                false_positives+=("$file")
            else
                real_threats+=("$file")
            fi
        done < "$infected_file"
    fi

    # Generate report
    {
        echo "MALWARE SCAN REPORT - $scan_date"
        echo "═══════════════════════════════════════════════════════════"
        echo ""
        echo "Scanned with: ImunifyAV, ClamAV, Linux Maldet, RKHunter"
        echo ""

        if [ ${#real_threats[@]} -eq 0 ]; then
            echo "RESULT: ✅ No malware found - your server is clean"
        else
            echo "RESULT: ⚠️  ${#real_threats[@]} infected file(s) detected"
            echo ""
            echo "INFECTED FILES:"
            for file in "${real_threats[@]}"; do
                echo "  • $file"
            done
            echo ""
            echo "NEXT STEPS:"
            echo "  1. Remove infected files immediately"
            echo "  2. Change all passwords"
            echo "  3. Update WordPress/plugins to latest versions"
        fi

        if [ ${#false_positives[@]} -gt 0 ]; then
            echo ""
            echo "───────────────────────────────────────────────────────────"
            echo "NOTE: Attack attempts were detected in your server logs."
            echo "These were successfully blocked. No action needed."
        fi

        echo ""
        echo "Scan ID: $session_name"
    } > "$report_file"

    # Display the report
    echo ""
    print_header "Client Security Report Generated"
    echo ""
    cat "$report_file"
    echo ""
    echo -e "${GREEN}Report saved to:${NC} $report_file"
    echo ""
    echo "You can now copy/paste this report into your support ticket."
    echo ""
}

# Main execution
main() {
    # Detect scanners (populate available_scanners array)
    # Don't exit if none found - menu option 9 allows installation
    detect_scanners || true

    # Cache scanner detection results (optimization: prevents redundant checks in menus)
    cache_scanner_detection

    # Verify show_scan_menu exists and is callable
    if ! declare -f "show_scan_menu" &>/dev/null; then
        echo "ERROR: show_scan_menu function not found" >&2
        return 1
    fi

    # Call the menu function
    show_scan_menu
}

# Run if executed directly
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
    main "$@"
fi
