#!/bin/bash

#
# Suspicious Login Monitor - Integrated Security Analysis & Compromise Detection
# Detects suspicious login patterns, correlates with web attack activity,
# and checks for actual system compromise indicators
# Supports: cPanel, Plesk, InterWorx, Standalone
#

# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TOOLKIT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

# Configuration
SUSPICIOUS_LOGIN_AUTO_BLOCK="${SUSPICIOUS_LOGIN_AUTO_BLOCK:-yes}"
SUSPICIOUS_LOGIN_AUTO_SCAN="${SUSPICIOUS_LOGIN_AUTO_SCAN:-yes}"
SUSPICIOUS_LOGIN_EMAIL_ALERTS="${SUSPICIOUS_LOGIN_EMAIL_ALERTS:-no}"

# Risk thresholds
RISK_CRITICAL=85
RISK_HIGH=70
RISK_MEDIUM=50

# False positive reduction settings
FP_CHECK_PACKAGE_LOGS="${FP_CHECK_PACKAGE_LOGS:-yes}"          # Check if changes from package updates
FP_REQUIRE_MULTIPLE_INDICATORS="${FP_REQUIRE_MULTIPLE_INDICATORS:-yes}"  # Lower risk if only 1 indicator
FP_IGNORE_BUSINESS_HOURS="${FP_IGNORE_BUSINESS_HOURS:-no}"      # Lower risk during business hours (9am-5pm)
FP_SSH_KEY_THRESHOLD="${FP_SSH_KEY_THRESHOLD:-10}"              # Number of SSH keys before flagging (default: 10)
FP_PASSWORD_CHANGE_THRESHOLD="${FP_PASSWORD_CHANGE_THRESHOLD:-5}" # Number of accounts before flagging mass change

# Whitelist/Ignore settings (can be comma-separated lists)
FP_WHITELIST_USERS="${FP_WHITELIST_USERS:-}"                    # Trusted users (e.g., "admin,bob,alice")
FP_WHITELIST_IPS="${FP_WHITELIST_IPS:-}"                        # Trusted IPs (e.g., "192.168.1.100,10.0.0.50")
FP_IGNORE_USERS="${FP_IGNORE_USERS:-}"                          # Users to ignore (e.g., "deploy,backup")
FP_SAFE_TIME_WINDOWS="${FP_SAFE_TIME_WINDOWS:-}"                # Safe maintenance windows (e.g., "Sun:02-04,*:03-03:30")
FP_MIN_ACCOUNT_AGE_DAYS="${FP_MIN_ACCOUNT_AGE_DAYS:-30}"        # Days before account considered "established"

# Integration paths
BOT_ANALYZER="$TOOLKIT_ROOT/modules/security/bot-analyzer.sh"
MALWARE_SCANNER="$TOOLKIT_ROOT/modules/security/malware-scanner.sh"
IP_REPUTATION_LIB="$TOOLKIT_ROOT/lib/ip-reputation.sh"
THREAT_INTEL_LIB="$TOOLKIT_ROOT/lib/threat-intelligence.sh"

# Temp files
TMP_DIR="/tmp"
REPORT_FILE="$TMP_DIR/suspicious_login_report_$(date +%Y%m%d_%H%M%S).txt"
SSH_EVENTS="$TMP_DIR/ssh_events_$$.txt"
PANEL_EVENTS="$TMP_DIR/panel_events_$$.txt"
SUDO_EVENTS="$TMP_DIR/sudo_events_$$.txt"
SUSPICIOUS_IPS="$TMP_DIR/suspicious_ips_$$.txt"

# Baseline storage (persistent across runs, within toolkit directory)
BASELINE_DIR="$TOOLKIT_ROOT/data/suspicious-login-monitor"
BASELINE_FILE="$BASELINE_DIR/baseline.dat"
mkdir -p "$BASELINE_DIR" 2>/dev/null

# Analysis period (default: last 24 hours)
HOURS="${1:-24}"

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

# Cleanup on exit
trap cleanup EXIT
cleanup() {
    rm -f "$SSH_EVENTS" "$PANEL_EVENTS" "$SUDO_EVENTS" "$SUSPICIOUS_IPS" 2>/dev/null
}

# Detect control panel
detect_panel() {
    if [ -d /usr/local/cpanel ]; then
        echo "cpanel"
    elif [ -d /usr/local/psa ]; then
        echo "plesk"
    elif [ -d /home/interworx ]; then
        echo "interworx"
    else
        echo "standalone"
    fi
}

# Get server IPs to exclude
get_server_ips() {
    {
        echo "127.0.0.1"
        echo "::1"
        ip addr | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v "^127\."
        ip addr | grep -oP '(?<=inet6\s)[0-9a-f:]+' | grep -v "^::1"
    } | sort -u
}

#
# SSH LOG PARSING
#

parse_ssh_logins() {
    local hours=$1
    local secure_log="/var/log/secure"

    # Use auth.log on Debian-based systems
    if [ ! -f "$secure_log" ] && [ -f "/var/log/auth.log" ]; then
        secure_log="/var/log/auth.log"
    fi

    if [ ! -f "$secure_log" ]; then
        return 0
    fi

    echo "  Parsing SSH login attempts..." >&2

    # Parse successful SSH logins
    awk -v hours="$hours" '
    BEGIN {
        # Calculate time threshold
        cmd = "date -d \"" hours " hours ago\" +%s"
        cmd | getline threshold
        close(cmd)
    }

    /sshd.*Accepted/ {
        # Parse timestamp
        timestamp = $1 " " $2 " " $3
        cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
        cmd | getline epoch
        close(cmd)

        if (epoch < threshold) next

        # Extract details
        user = ""
        ip = ""
        method = ""

        # Accepted password for user from ip
        if (match($0, /Accepted (password|publickey) for ([^ ]+) from ([^ ]+)/)) {
            method = (index($0, "publickey") > 0) ? "key" : "password"
            for (i=1; i<=NF; i++) {
                if ($i == "for") user = $(i+1)
                if ($i == "from") ip = $(i+1)
            }
        }

        if (user != "" && ip != "") {
            print timestamp "|" user "|" ip "|ssh|" method "|success"
        }
    }

    /sshd.*Failed/ {
        # Parse timestamp
        timestamp = $1 " " $2 " " $3
        cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
        cmd | getline epoch
        close(cmd)

        if (epoch < threshold) next

        # Extract details
        user = ""
        ip = ""

        # Failed password for user from ip
        if (match($0, /Failed password for/)) {
            for (i=1; i<=NF; i++) {
                if ($i == "for") user = $(i+1)
                if ($i == "from") ip = $(i+1)
            }
        }

        if (user != "" && ip != "") {
            print timestamp "|" user "|" ip "|ssh|password|failed"
        }
    }
    ' "$secure_log" > "$SSH_EVENTS"
}

#
# WTMP LOG PARSING (Universal - All Panels)
#

parse_wtmp_logins() {
    local hours=$1

    if [ ! -f /var/log/wtmp ]; then
        return 0
    fi

    echo "  Parsing session history (wtmp)..." >&2

    # Calculate cutoff date for last command
    local cutoff_date=$(date -d "$hours hours ago" "+%Y-%m-%d %H:%M:%S")

    # Use last command to parse binary wtmp log
    # Format: user tty ip datetime - datetime (duration)
    last -F 2>/dev/null | awk -v cutoff="$cutoff_date" '
    BEGIN {
        # Convert cutoff to epoch
        cmd = "date -d \"" cutoff "\" +%s"
        cmd | getline cutoff_epoch
        close(cmd)
    }

    /^[a-zA-Z0-9]/ && !/^reboot/ && !/^wtmp/ {
        # Skip header lines
        if ($1 == "USER" || $1 == "wtmp") next

        user = $1
        tty = $2
        ip = $3

        # Parse login time: "Mon Feb  2 18:59:03 2026"
        month = $4
        day = $5
        time = $6
        year = $7

        # Check if still logged in or logged out
        if ($9 == "still") {
            status = "active"
        } else {
            status = "success"
        }

        # Build timestamp for comparison
        timestamp = month " " day " " time " " year
        cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
        cmd | getline login_epoch
        close(cmd)

        # Only include logins within time window
        if (login_epoch >= cutoff_epoch) {
            # Normalize timestamp format
            simple_timestamp = month " " day " " time

            # Determine auth method (if from pts/pty, assume key; if no IP, skip)
            method = "key"
            if (ip == "" || ip == "-" || ip == ":0" || ip == "localhost") {
                next  # Skip local logins
            }

            print simple_timestamp "|" user "|" ip "|ssh|" method "|" status
        }
    }
    ' >> "$SSH_EVENTS"
}

#
# BTMP LOG PARSING (Universal - All Panels)
#

parse_btmp_logins() {
    local hours=$1

    if [ ! -f /var/log/btmp ]; then
        return 0
    fi

    echo "  Parsing failed logins (btmp)..." >&2

    # Calculate cutoff date
    local cutoff_date=$(date -d "$hours hours ago" "+%Y-%m-%d %H:%M:%S")

    # Use lastb command to parse binary btmp log
    lastb -F 2>/dev/null | awk -v cutoff="$cutoff_date" '
    BEGIN {
        cmd = "date -d \"" cutoff "\" +%s"
        cmd | getline cutoff_epoch
        close(cmd)
    }

    /^[a-zA-Z0-9]/ && !/^btmp/ {
        # Skip header
        if ($1 == "USERNAME" || $1 == "btmp") next

        user = $1
        tty = $2
        ip = $3

        # Parse timestamp: "Mon Feb  2 19:18:10 2026"
        month = $4
        day = $5
        time = $6
        year = $7

        timestamp = month " " day " " time " " year
        cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
        cmd | getline login_epoch
        close(cmd)

        # Only include failed attempts within time window
        if (login_epoch >= cutoff_epoch) {
            simple_timestamp = month " " day " " time

            # Skip if no IP
            if (ip == "" || ip == "-") next

            print simple_timestamp "|" user "|" ip "|ssh|password|failed"
        }
    }
    ' >> "$SSH_EVENTS"
}

#
# SUDO/PRIVILEGE ESCALATION DETECTION (Universal - All Panels)
#

parse_sudo_escalation() {
    local hours=$1
    local secure_log="/var/log/secure"

    # Use auth.log on Debian-based systems
    if [ ! -f "$secure_log" ] && [ -f "/var/log/auth.log" ]; then
        secure_log="/var/log/auth.log"
    fi

    if [ ! -f "$secure_log" ]; then
        return 0
    fi

    echo "  Detecting sudo/privilege escalation..." >&2

    # Parse sudo commands from secure log
    awk -v hours="$hours" '
    BEGIN {
        cmd = "date -d \"" hours " hours ago\" +%s"
        cmd | getline threshold
        close(cmd)
    }

    /sudo:/ {
        # Parse timestamp
        timestamp = $1 " " $2 " " $3
        cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
        cmd | getline epoch
        close(cmd)

        if (epoch < threshold) next

        # Extract user and command
        # Format: "user : TTY=pts/0 ; PWD=/root ; USER=root ; COMMAND=/bin/bash"
        user = ""
        target_user = ""
        sudo_cmd = ""

        # Find the username before the colon
        for (i=1; i<=NF; i++) {
            if ($i == "sudo:") {
                user = $(i+1)
                break
            }
        }

        # Extract TARGET user (USER=root)
        if (match($0, /USER=([^ ;]+)/)) {
            target_user_match = substr($0, RSTART+5)
            split(target_user_match, arr, " ")
            target_user = arr[1]
            gsub(/;/, "", target_user)
        }

        # Extract COMMAND
        if (match($0, /COMMAND=(.+)$/)) {
            sudo_cmd = substr($0, RSTART+8)
        }

        # Determine if this is a privilege escalation to root
        if (target_user == "root" && user != "root") {
            # Non-root user executing sudo to root
            print timestamp "|" user "|localhost|sudo|escalation|" target_user "|" sudo_cmd
        }
    }
    ' "$secure_log" > "$TMP_DIR/sudo_events_$$.txt"
}

#
# CPANEL LOG PARSING
#

parse_cpanel_logins() {
    local hours=$1
    local whm_log="/usr/local/cpanel/logs/access_log"
    local cpanel_log="/usr/local/cpanel/logs/login_log"

    echo "  Parsing cPanel/WHM logins..." >&2

    # WHM access log
    if [ -f "$whm_log" ]; then
        awk -v hours="$hours" '
        BEGIN {
            cmd = "date -d \"" hours " hours ago\" +%s"
            cmd | getline threshold
            close(cmd)
        }

        {
            # Parse timestamp [01/Feb/2026:19:30:00]
            if (match($4, /\[([0-9]{2})\/([A-Za-z]{3})\/([0-9]{4}):([0-9:]+)\]/)) {
                timestamp_str = substr($4, 2)
                cmd = "date -d \"" timestamp_str "\" +\"%b %d %H:%M:%S\" 2>/dev/null"
                cmd | getline timestamp
                close(cmd)

                cmd = "date -d \"" timestamp_str "\" +%s 2>/dev/null"
                cmd | getline epoch
                close(cmd)

                if (epoch < threshold) next

                # Extract IP (first field)
                ip = $1

                # Check for WHM login
                if (match($0, /POST \/login\//) || match($0, /GET \/cpsess/)) {
                    # Extract user from URL if possible
                    user = "root"  # WHM is root access
                    status = "success"
                    if ($9 ~ /^(40|50)/) status = "failed"

                    print timestamp "|" user "|" ip "|whm|web|" status
                }
            }
        }
        ' "$whm_log" >> "$PANEL_EVENTS"
    fi

    # cPanel login log
    if [ -f "$cpanel_log" ]; then
        awk -v hours="$hours" '
        BEGIN {
            cmd = "date -d \"" hours " hours ago\" +%s"
            cmd | getline threshold
            close(cmd)
        }

        {
            # Parse timestamp
            timestamp = $1 " " $2 " " $3
            cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
            cmd | getline epoch
            close(cmd)

            if (epoch < threshold) next

            # Extract user and IP
            if (match($0, /user: ([^ ]+).*ip: ([^ ]+)/)) {
                for (i=1; i<=NF; i++) {
                    if ($i == "user:") user = $(i+1)
                    if ($i == "ip:") ip = $(i+1)
                }

                status = (match($0, /FAILED/) || match($0, /failed/)) ? "failed" : "success"

                if (user != "" && ip != "") {
                    print timestamp "|" user "|" ip "|cpanel|web|" status
                }
            }
        }
        ' "$cpanel_log" >> "$PANEL_EVENTS"
    fi

    # cPanel session log (WHM Terminal access)
    local session_log="/usr/local/cpanel/logs/session_log"
    if [ -f "$session_log" ]; then
        awk -v hours="$hours" '
        BEGIN {
            cmd = "date -d \"" hours " hours ago\" +%s"
            cmd | getline threshold
            close(cmd)
        }

        /NEW/ && /whostmgrd/ {
            # Parse timestamp: [2026-01-05 19:40:56 -0500]
            if (match($0, /\[([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})/)) {
                timestamp_str = substr($0, RSTART+1, RLENGTH-1)

                # Convert to epoch for comparison
                cmd = "date -d \"" timestamp_str "\" +%s 2>/dev/null"
                cmd | getline epoch
                close(cmd)

                if (epoch < threshold) next

                # Convert to simple format for output
                cmd = "date -d \"" timestamp_str "\" \"+%b %d %H:%M:%S\" 2>/dev/null"
                cmd | getline timestamp
                close(cmd)

                # Extract IP from "address=IP"
                ip = ""
                if (match($0, /address=([0-9.]+)/)) {
                    ip_match = substr($0, RSTART+8)
                    split(ip_match, arr, ",")
                    ip = arr[1]
                }

                # Extract user (usually root for WHM terminal)
                user = "root"
                if (match($0, /creator=([^ ,]+)/)) {
                    user_match = substr($0, RSTART+8)
                    split(user_match, arr, ",")
                    user = arr[1]
                }

                if (ip != "" && ip != "internal") {
                    print timestamp "|" user "|" ip "|whm-terminal|web|success"
                }
            }
        }
        ' "$session_log" >> "$PANEL_EVENTS"
    fi
}

#
# PLESK LOG PARSING
#

parse_plesk_logins() {
    local hours=$1
    local plesk_log="/var/log/plesk/panel.log"

    # Try alternative location
    if [ ! -f "$plesk_log" ]; then
        plesk_log="/usr/local/psa/var/log/panel.log"
    fi

    if [ ! -f "$plesk_log" ]; then
        return 0
    fi

    echo "  Parsing Plesk panel logins..." >&2

    awk -v hours="$hours" '
    BEGIN {
        cmd = "date -d \"" hours " hours ago\" +%s"
        cmd | getline threshold
        close(cmd)
    }

    /login/ {
        # Parse timestamp (ISO format: 2026-02-02 19:30:00)
        timestamp = $1 " " $2
        cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
        cmd | getline epoch
        close(cmd)

        if (epoch < threshold) next

        # Extract user and IP
        user = ""
        ip = ""
        status = "success"

        if (match($0, /user=([^ ]+)/)) {
            for (i=1; i<=NF; i++) {
                if (match($i, /user=/)) {
                    gsub(/user=/, "", $i)
                    user = $i
                }
                if (match($i, /ip=/)) {
                    gsub(/ip=/, "", $i)
                    ip = $i
                }
            }
        }

        if (match($0, /failed/)) status = "failed"

        if (user != "" && ip != "") {
            print timestamp "|" user "|" ip "|plesk|web|" status
        }
    }
    ' "$plesk_log" >> "$PANEL_EVENTS"
}

#
# INTERWORX LOG PARSING
#

parse_interworx_logins() {
    local hours=$1
    local iworx_log="/home/interworx/var/log/iworx.log"
    local siteworx_log="/home/interworx/var/log/siteworx.log"

    if [ ! -f "$iworx_log" ]; then
        return 0
    fi

    echo "  Parsing InterWorx logins..." >&2

    # Parse NodeWorx (admin) logins
    awk -v hours="$hours" '
    BEGIN {
        cmd = "date -d \"" hours " hours ago\" +%s"
        cmd | getline threshold
        close(cmd)
    }

    /login/ {
        timestamp = $1 " " $2
        cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
        cmd | getline epoch
        close(cmd)

        if (epoch < threshold) next

        # Extract details
        user = ""
        ip = ""
        status = "success"

        for (i=1; i<=NF; i++) {
            if (match($i, /user=/)) {
                gsub(/user=/, "", $i)
                user = $i
            }
            if (match($i, /ip=/)) {
                gsub(/ip=/, "", $i)
                ip = $i
            }
        }

        if (match($0, /failed/)) status = "failed"

        if (user != "" && ip != "") {
            print timestamp "|" user "|" ip "|interworx|web|" status
        }
    }
    ' "$iworx_log" >> "$PANEL_EVENTS"

    # Parse SiteWorx (user/site owner) logins
    if [ -f "$siteworx_log" ]; then
        awk -v hours="$hours" '
        BEGIN {
            cmd = "date -d \"" hours " hours ago\" +%s"
            cmd | getline threshold
            close(cmd)
        }

        /login/ {
            timestamp = $1 " " $2
            cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
            cmd | getline epoch
            close(cmd)

            if (epoch < threshold) next

            # Extract details
            user = ""
            ip = ""
            status = "success"

            for (i=1; i<=NF; i++) {
                if (match($i, /user=/)) {
                    gsub(/user=/, "", $i)
                    user = $i
                }
                if (match($i, /ip=/)) {
                    gsub(/ip=/, "", $i)
                    ip = $i
                }
            }

            if (match($0, /failed/)) status = "failed"

            if (user != "" && ip != "") {
                print timestamp "|" user "|" ip "|siteworx|web|" status
            }
        }
        ' "$siteworx_log" >> "$PANEL_EVENTS"
    fi
}

#
# ANOMALY DETECTION
#

detect_anomalies() {
    echo "  Analyzing login patterns..." >&2

    # Combine all events (including sudo)
    cat "$SSH_EVENTS" "$PANEL_EVENTS" "$SUDO_EVENTS" 2>/dev/null | \
    awk -F'|' -v server_ips="$(get_server_ips | tr '\n' '|')" '
    {
        timestamp = $1
        user = $2
        ip = $3
        service = $4
        method = $5
        status = $6

        # Skip server IPs (but not localhost for sudo events)
        if (service != "sudo" && index(server_ips, ip "|") > 0) next

        # Skip cPanel internal IPs
        if (match(ip, /^(208\.74\.123\.|184\.94\.197\.)/)) next

        # Track all events by IP (use "local" for sudo events)
        event_key = (ip == "localhost") ? "LOCAL_SUDO" : ip
        ip_events[event_key]++
        ip_users[event_key] = ip_users[event_key] (ip_users[event_key] ? "," : "") user

        # Track sudo escalation events (method == "escalation")
        if (method == "escalation") {
            sudo_escalations[event_key]++
            sudo_users[event_key] = sudo_users[event_key] (sudo_users[event_key] ? "," : "") user
            # status field contains target_user for sudo
            sudo_targets[event_key] = sudo_targets[event_key] (sudo_targets[event_key] ? "," : "") status
        }

        # Track failed attempts
        if (status == "failed") {
            failed[event_key]++
            failed_users[event_key] = failed_users[event_key] (failed_users[event_key] ? "," : "") user
        }

        # Track successful logins
        if (status == "success" || status == "active") {
            successful[event_key]++
            successful_users[event_key] = successful_users[event_key] (successful_users[event_key] ? "," : "") user
            successful_services[event_key] = successful_services[event_key] (successful_services[event_key] ? "," : "") service

            # Track root access
            if (user == "root") {
                root_logins[event_key]++
                root_methods[event_key] = root_methods[event_key] (root_methods[event_key] ? "," : "") method
            }

            # Track password vs key auth
            if (method == "password") {
                password_auth[event_key]++
            } else if (method == "key") {
                key_auth[event_key]++
            }
        }

        # Store first and last seen
        if (first_seen[event_key] == "") {
            first_seen[event_key] = timestamp
        }
        last_seen[event_key] = timestamp
    }
    END {
        for (ip in ip_events) {
            risk = 0
            reasons = ""

            # Root access risk
            if (root_logins[ip] > 0) {
                risk += 20
                reasons = reasons "Root-Access "

                # Password auth for root (higher risk)
                if (index(root_methods[ip], "password") > 0) {
                    risk += 10
                    reasons = reasons "Root-Password-Auth "
                }
            }

            # Failed login risk
            if (failed[ip] > 0) {
                fail_score = failed[ip] * 5
                if (fail_score > 25) fail_score = 25
                risk += fail_score
                reasons = reasons "Failed-Attempts(" failed[ip] ") "

                # Failed root attempts (very suspicious)
                if (index(failed_users[ip], "root") > 0) {
                    risk += 15
                    reasons = reasons "Failed-Root "
                }
            }

            # Brute force detection
            if (failed[ip] >= 5) {
                risk += 20
                reasons = reasons "Brute-Force "
            }

            # Multiple users from same IP (potential attack)
            split(ip_users[ip], user_arr, ",")
            unique_users = 0
            for (u in user_arr) unique_users++
            if (unique_users > 3) {
                risk += 15
                reasons = reasons "Multiple-Users(" unique_users ") "
            }

            # Password auth risk (should use keys)
            if (password_auth[ip] > 0 && key_auth[ip] == 0) {
                risk += 5
                reasons = reasons "Password-Only "
            }

            # Sudo escalation risk
            if (sudo_escalations[ip] > 0) {
                risk += 15
                reasons = reasons "Sudo-Escalation(" sudo_escalations[ip] ") "
            }

            # Cap at 100
            if (risk > 100) risk = 100

            # Only report suspicious IPs (risk >= 30)
            if (risk >= 30) {
                print ip "|" risk "|" reasons "|" successful[ip] "|" failed[ip] "|" root_logins[ip] "|" ip_users[ip] "|" successful_services[ip]
            }
        }
    }
    ' | sort -t'|' -k2 -nr > "$SUSPICIOUS_IPS"
}

#
# BOT ANALYZER INTEGRATION
#

correlate_with_access_logs() {
    local ip=$1
    local risk_score=$2

    # Find most recent bot analyzer report
    local latest_report=$(ls -t "$TOOLKIT_ROOT"/tmp/bot_analysis_report_*.txt /tmp/bot_analysis_report_*.txt 2>/dev/null | head -n1)

    if [ -z "$latest_report" ]; then
        echo "0|No bot analyzer data available"
        return 0
    fi

    # Check if this IP appears in bot analyzer results
    local ip_data=$(grep -w "$ip" "$latest_report" 2>/dev/null || echo "")

    if [ -z "$ip_data" ]; then
        echo "0|No access log activity"
        return 0
    fi

    # Extract attack vectors from bot analyzer report
    local attack_vectors=""
    local additional_risk=0

    # Look for attack patterns in the report around this IP
    local context=$(grep -w -A 5 -B 5 "$ip" "$latest_report" 2>/dev/null)

    # Check for specific attack types
    if echo "$context" | grep -qi "RCE/Upload"; then
        attack_vectors="$attack_vectors RCE/Upload"
        additional_risk=$((additional_risk + 25))
    fi

    if echo "$context" | grep -qi "SQLi\|SQL injection"; then
        attack_vectors="$attack_vectors SQLi"
        additional_risk=$((additional_risk + 20))
    fi

    if echo "$context" | grep -qi "Admin.*prob\|wp-login\|admin login"; then
        attack_vectors="$attack_vectors Admin-Probe"
        additional_risk=$((additional_risk + 15))
    fi

    if echo "$context" | grep -qi "Login.*Brute\|brute.*force"; then
        attack_vectors="$attack_vectors Login-Bruteforce"
        additional_risk=$((additional_risk + 15))
    fi

    if echo "$context" | grep -qi "Info.*Disclosure\|info disclosure"; then
        attack_vectors="$attack_vectors Info-Disclosure"
        additional_risk=$((additional_risk + 10))
    fi

    if echo "$context" | grep -qi "XSS"; then
        attack_vectors="$attack_vectors XSS"
        additional_risk=$((additional_risk + 10))
    fi

    # Cap at 100
    local new_risk=$((risk_score + additional_risk))
    [ "$new_risk" -gt 100 ] && new_risk=100

    echo "$additional_risk|$attack_vectors"
}

#
# IP REPUTATION CHECK
#

check_ip_reputation() {
    local ip=$1
    local risk_score=$2

    # Source IP reputation library if available
    if [ ! -f "$IP_REPUTATION_LIB" ]; then
        echo "0|IP reputation library not available"
        return 0
    fi

    source "$IP_REPUTATION_LIB"

    local additional_risk=0
    local notes=""

    # Check whitelist
    if is_whitelisted "$ip" 2>/dev/null; then
        echo "-30|Whitelisted IP"
        return 0
    fi

    # Check blacklist
    if is_blacklisted "$ip" 2>/dev/null; then
        additional_risk=$((additional_risk + 20))
        notes="$notes Previously-Blacklisted"
    fi

    # Check reputation score
    local reputation=$(get_ip_reputation "$ip" 2>/dev/null)
    if [ -n "$reputation" ] && [ "$reputation" -lt 40 ]; then
        additional_risk=$((additional_risk + 15))
        notes="$notes Poor-Reputation($reputation)"
    fi

    echo "$additional_risk|$notes"
}

#
# THREAT INTELLIGENCE CORRELATION
#

correlate_with_threat_intel() {
    local ip=$1

    # Source threat intelligence library if available
    if [ ! -f "$THREAT_INTEL_LIB" ]; then
        echo "0|Threat intelligence not available"
        return 0
    fi

    source "$THREAT_INTEL_LIB"

    local additional_risk=0
    local notes=""

    # Check known botnets
    if is_known_botnet "$ip" 2>/dev/null; then
        additional_risk=$((additional_risk + 30))
        notes="$notes Known-Botnet"
    fi

    # GeoIP check (if available)
    if command -v geoiplookup &>/dev/null; then
        local country=$(geoiplookup "$ip" 2>/dev/null | awk -F': ' '{print $2}' | head -n1)
        if [ -n "$country" ]; then
            notes="$notes Country:$country"
            # High-risk countries
            case "$country" in
                *China*|*Russia*|*North\ Korea*)
                    additional_risk=$((additional_risk + 10))
                    notes="$notes High-Risk-Geo"
                    ;;
            esac
        fi
    fi

    echo "$additional_risk|$notes"
}

#
# CONFIDENCE IMPROVEMENT - Baseline and pattern matching
#

load_baseline() {
    # Load historical baseline data
    if [ -f "$BASELINE_FILE" ]; then
        source "$BASELINE_FILE"
    else
        # Initialize empty baseline
        BASELINE_SSH_KEY_COUNT=0
        BASELINE_USER_COUNT=0
        BASELINE_TYPICAL_LOGIN_HOURS=""
        BASELINE_PASSWORD_CHANGES_PER_WEEK=0
        BASELINE_NEW_USERS_PER_WEEK=0
        BASELINE_LAST_UPDATE=0
    fi
}

save_baseline() {
    local ssh_key_count=$1
    local user_count=$2
    local login_hours=$3
    local pw_changes=$4
    local new_users=$5

    cat > "$BASELINE_FILE" << EOF
# Baseline data for suspicious login monitor
# Last updated: $(date)
BASELINE_SSH_KEY_COUNT=$ssh_key_count
BASELINE_USER_COUNT=$user_count
BASELINE_TYPICAL_LOGIN_HOURS="$login_hours"
BASELINE_PASSWORD_CHANGES_PER_WEEK=$pw_changes
BASELINE_NEW_USERS_PER_WEEK=$new_users
BASELINE_LAST_UPDATE=$(date +%s)
EOF
}

update_baseline() {
    # Update baseline with current system state
    local current_keys=$(grep -v "^#" /root/.ssh/authorized_keys 2>/dev/null | grep -c "ssh-" || echo 0)
    local current_users=$(awk -F: '$3 >= 1000 && $3 < 60000 {print $1}' /etc/passwd | wc -l)
    local typical_hours=$(who | awk '{print $4}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -3 | awk '{print $2}' | tr '\n' ',' | sed 's/,$//')

    # Track password changes and user creation over time
    local pw_changes=0
    local new_users=0

    # Simple tracking - could be enhanced with historical analysis
    if [ -f "$BASELINE_FILE" ]; then
        source "$BASELINE_FILE"
        # Use existing values as basis
    fi

    save_baseline "$current_keys" "$current_users" "$typical_hours" "$pw_changes" "$new_users"
}

check_deviation_from_baseline() {
    local metric=$1
    local current_value=$2
    local baseline_value=$3

    # Calculate percentage deviation
    if [ "$baseline_value" -eq 0 ]; then
        echo "100"  # New metric, 100% deviation
        return
    fi

    local diff=$((current_value - baseline_value))
    local abs_diff=${diff#-}  # Absolute value
    local percent=$((abs_diff * 100 / baseline_value))

    echo "$percent"
}

match_attack_patterns() {
    local findings=$1
    local confidence_boost=0
    local matched_patterns=""

    # Known attack pattern signatures
    # Pattern 1: Backdoor account + SSH key + recent creation
    if echo "$findings" | grep -q "UID-0" && \
       echo "$findings" | grep -q "SSH-Key" && \
       echo "$findings" | grep -q "Created-Users"; then
        confidence_boost=$((confidence_boost + 30))
        matched_patterns="${matched_patterns}Backdoor-Installation-Pattern "
    fi

    # Pattern 2: Mass password change + file tampering
    if echo "$findings" | grep -q "Mass-Password" && \
       echo "$findings" | grep -q "Modified"; then
        confidence_boost=$((confidence_boost + 25))
        matched_patterns="${matched_patterns}Ransomware-Pattern "
    fi

    # Pattern 3: Sudo escalation + suspicious process + cron
    if echo "$findings" | grep -q "Sudo" && \
       echo "$findings" | grep -q "Process" && \
       echo "$findings" | grep -q "Cron"; then
        confidence_boost=$((confidence_boost + 30))
        matched_patterns="${matched_patterns}Privilege-Escalation-Pattern "
    fi

    # Pattern 4: Web shell + backdoor cron + network activity
    if echo "$findings" | grep -q "Shell" && \
       echo "$findings" | grep -q "Cron" && \
       echo "$findings" | grep -q "Network"; then
        confidence_boost=$((confidence_boost + 35))
        matched_patterns="${matched_patterns}Persistent-Backdoor-Pattern "
    fi

    # Pattern 5: Rootkit indicators + modified binaries + hidden files
    if echo "$findings" | grep -q "Rootkit" && \
       echo "$findings" | grep -q "Binary" && \
       echo "$findings" | grep -q "Hidden"; then
        confidence_boost=$((confidence_boost + 40))
        matched_patterns="${matched_patterns}Rootkit-Compromise-Pattern "
    fi

    # Pattern 6: Recently created user + suspicious name + no password age
    if echo "$findings" | grep -q "Suspicious-Username" && \
       echo "$findings" | grep -q "Created-Users" && \
       echo "$findings" | grep -q "Password"; then
        confidence_boost=$((confidence_boost + 25))
        matched_patterns="${matched_patterns}Account-Takeover-Pattern "
    fi

    echo "$confidence_boost|$matched_patterns"
}

calculate_confidence_score() {
    local risk=$1
    local findings=$2
    local mitigating_factors=$3

    # Start with base confidence from risk level
    local confidence=50  # Medium baseline

    # Risk-based confidence adjustment
    if [ "$risk" -ge 85 ]; then
        confidence=$((confidence + 30))  # High risk = higher confidence it's real
    elif [ "$risk" -ge 70 ]; then
        confidence=$((confidence + 20))
    elif [ "$risk" -ge 50 ]; then
        confidence=$((confidence + 10))
    fi

    # Multiple independent indicators increase confidence
    local indicator_count=$(echo "$findings" | grep -o "[A-Z][a-z]*-[A-Z]" | wc -l)
    if [ "$indicator_count" -ge 5 ]; then
        confidence=$((confidence + 25))
    elif [ "$indicator_count" -ge 3 ]; then
        confidence=$((confidence + 15))
    elif [ "$indicator_count" -ge 2 ]; then
        confidence=$((confidence + 5))
    else
        confidence=$((confidence - 20))  # Single indicator = lower confidence
    fi

    # Mitigating factors reduce confidence
    local mitigation_count=$(echo "$mitigating_factors" | grep -o "\[" | wc -l)
    if [ "$mitigation_count" -ge 3 ]; then
        confidence=$((confidence - 30))  # Lots of context = probably legitimate
    elif [ "$mitigation_count" -ge 2 ]; then
        confidence=$((confidence - 20))
    elif [ "$mitigation_count" -ge 1 ]; then
        confidence=$((confidence - 10))
    fi

    # Check for attack pattern matches (increases confidence)
    local pattern_match=$(match_attack_patterns "$findings")
    local pattern_boost=$(echo "$pattern_match" | cut -d'|' -f1)
    local patterns=$(echo "$pattern_match" | cut -d'|' -f2-)

    confidence=$((confidence + pattern_boost))

    # Check baseline deviations (if available)
    if [ -f "$BASELINE_FILE" ]; then
        load_baseline

        # Check SSH key deviation
        local current_keys=$(grep -v "^#" /root/.ssh/authorized_keys 2>/dev/null | grep -c "ssh-" || echo 0)
        if [ "$BASELINE_SSH_KEY_COUNT" -gt 0 ]; then
            local key_deviation=$(check_deviation_from_baseline "keys" "$current_keys" "$BASELINE_SSH_KEY_COUNT")
            if [ "$key_deviation" -gt 50 ]; then
                confidence=$((confidence + 15))  # Significant deviation from normal
            fi
        fi
    fi

    # Cap confidence at 0-100
    [ "$confidence" -lt 0 ] && confidence=0
    [ "$confidence" -gt 100 ] && confidence=100

    # Determine confidence level
    local confidence_level="MEDIUM"
    if [ "$confidence" -ge 75 ]; then
        confidence_level="HIGH"
    elif [ "$confidence" -lt 40 ]; then
        confidence_level="LOW"
    fi

    echo "$confidence|$confidence_level|$patterns"
}

cross_validate_finding() {
    local finding_type=$1
    local finding_data=$2
    local validation_score=0
    local validation_sources=""

    case "$finding_type" in
        "password-change")
            # Cross-check with multiple sources
            # 1. /etc/shadow timestamp
            if [ -f /etc/shadow ]; then
                local shadow_age=$(($(date +%s) - $(stat -c %Y /etc/shadow)))
                if [ "$shadow_age" -lt 86400 ]; then
                    validation_score=$((validation_score + 1))
                    validation_sources="${validation_sources}shadow-timestamp "
                fi
            fi

            # 2. /var/log/secure entries
            if grep -q "password changed" /var/log/secure 2>/dev/null; then
                validation_score=$((validation_score + 1))
                validation_sources="${validation_sources}secure-log "
            fi

            # 3. Audit log entries (if available)
            if [ -f /var/log/audit/audit.log ] && ausearch -m USER_CHAUTHTOK -ts recent >/dev/null 2>&1; then
                validation_score=$((validation_score + 1))
                validation_sources="${validation_sources}audit-log "
            fi
            ;;

        "user-creation")
            # 1. /etc/passwd timestamp
            local passwd_age=$(($(date +%s) - $(stat -c %Y /etc/passwd)))
            if [ "$passwd_age" -lt 604800 ]; then  # 7 days
                validation_score=$((validation_score + 1))
                validation_sources="${validation_sources}passwd-timestamp "
            fi

            # 2. Home directory existence and age
            local username=$(echo "$finding_data" | cut -d'(' -f1)
            if [ -d "/home/$username" ]; then
                validation_score=$((validation_score + 1))
                validation_sources="${validation_sources}home-dir-exists "
            fi

            # 3. System logs
            if grep -q "new user" /var/log/secure 2>/dev/null | grep -q "$username"; then
                validation_score=$((validation_score + 1))
                validation_sources="${validation_sources}secure-log "
            fi
            ;;

        "ssh-key")
            # 1. File modification time
            if [ -f /root/.ssh/authorized_keys ]; then
                local key_age=$(($(date +%s) - $(stat -c %Y /root/.ssh/authorized_keys)))
                if [ "$key_age" -lt 604800 ]; then
                    validation_score=$((validation_score + 1))
                    validation_sources="${validation_sources}key-file-timestamp "
                fi
            fi

            # 2. SSH log entries
            if grep -q "Accepted publickey" /var/log/secure 2>/dev/null | tail -100 | grep -q "root"; then
                validation_score=$((validation_score + 1))
                validation_sources="${validation_sources}ssh-log "
            fi
            ;;
    esac

    echo "$validation_score|$validation_sources"
}

#
# FALSE POSITIVE REDUCTION - Context checking functions
#

check_package_manager_activity() {
    local hours_ago=${1:-24}

    # Check YUM/DNF logs
    if [ -f /var/log/yum.log ]; then
        local yum_activity=$(find /var/log/yum.log -mmin -$((hours_ago * 60)) 2>/dev/null)
        if [ -n "$yum_activity" ]; then
            local recent_installs=$(grep -E "Installed|Updated" /var/log/yum.log 2>/dev/null | tail -5 | wc -l)
            if [ "$recent_installs" -gt 0 ]; then
                echo "yum_activity"
                return 0
            fi
        fi
    fi

    # Check APT logs
    if [ -f /var/log/apt/history.log ]; then
        local apt_activity=$(find /var/log/apt/history.log -mmin -$((hours_ago * 60)) 2>/dev/null)
        if [ -n "$apt_activity" ]; then
            echo "apt_activity"
            return 0
        fi
    fi

    # Check cPanel update logs
    if [ -d /var/cpanel/updatelogs ]; then
        local cpanel_update=$(find /var/cpanel/updatelogs/ -name "update.*.log" -mmin -$((hours_ago * 60)) 2>/dev/null | head -1)
        if [ -n "$cpanel_update" ]; then
            echo "cpanel_update"
            return 0
        fi
    fi

    echo "none"
    return 1
}

is_business_hours() {
    local hour=$(date +%H)
    local day=$(date +%u)  # 1=Monday, 7=Sunday

    # Monday-Friday, 9am-5pm
    if [ "$day" -le 5 ] && [ "$hour" -ge 9 ] && [ "$hour" -lt 17 ]; then
        return 0
    fi
    return 1
}

check_cpanel_account_creation() {
    local hours_ago=${1:-24}

    # Check cPanel access log for account creation
    if [ -f /usr/local/cpanel/logs/access_log ]; then
        local account_creation=$(grep -E "createacct|\/json-api\/cpanel\?cpanel_jsonapi_module=Accounts" /usr/local/cpanel/logs/access_log 2>/dev/null | tail -1)
        if [ -n "$account_creation" ]; then
            echo "cpanel_account_creation"
            return 0
        fi
    fi

    echo "none"
    return 1
}

get_process_parent() {
    local pid=$1
    ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' '
}

is_legitimate_parent() {
    local ppid=$1
    local parent_name=$(ps -o comm= -p "$ppid" 2>/dev/null)

    # Legitimate parent processes
    case "$parent_name" in
        yum|dnf|apt|apt-get|dpkg|cpanelsync|upcp|ea-update|sshd|systemd)
            return 0
            ;;
    esac
    return 1
}

is_whitelisted_user() {
    local user=$1

    if [ -z "$FP_WHITELIST_USERS" ]; then
        return 1
    fi

    # Check if user is in whitelist
    echo "$FP_WHITELIST_USERS" | grep -q "\b$user\b"
    return $?
}

is_whitelisted_ip() {
    local ip=$1

    if [ -z "$FP_WHITELIST_IPS" ]; then
        return 1
    fi

    # Check if IP is in whitelist
    echo "$FP_WHITELIST_IPS" | grep -q "\b$ip\b"
    return $?
}

is_ignored_user() {
    local user=$1

    if [ -z "$FP_IGNORE_USERS" ]; then
        return 1
    fi

    # Check if user is in ignore list
    echo "$FP_IGNORE_USERS" | grep -q "\b$user\b"
    return $?
}

is_safe_time_window() {
    local current_day=$(date +%a)  # Mon, Tue, Wed, etc.
    local current_hour=$(date +%H)
    local current_min=$(date +%M)
    local current_time="$current_hour:$current_min"

    if [ -z "$FP_SAFE_TIME_WINDOWS" ]; then
        return 1
    fi

    # Parse safe time windows: "Sun:02-04,*:03-03:30"
    # Format: Day:StartHour-EndHour or *:StartTime-EndTime
    IFS=',' read -ra WINDOWS <<< "$FP_SAFE_TIME_WINDOWS"
    for window in "${WINDOWS[@]}"; do
        local day_part=$(echo "$window" | cut -d: -f1)
        local time_part=$(echo "$window" | cut -d: -f2)

        # Check day match (* = any day)
        if [ "$day_part" = "*" ] || [ "$day_part" = "$current_day" ]; then
            local start_time=$(echo "$time_part" | cut -d- -f1)
            local end_time=$(echo "$time_part" | cut -d- -f2)

            # Simple hour comparison (could be enhanced for minutes)
            local start_hour=$(echo "$start_time" | cut -d: -f1)
            local end_hour=$(echo "$end_time" | cut -d: -f1)

            if [ "$current_hour" -ge "$start_hour" ] && [ "$current_hour" -le "$end_hour" ]; then
                return 0
            fi
        fi
    done

    return 1
}

check_active_admin_session() {
    local hours_ago=${1:-1}

    # Check if any admin is currently logged in via SSH
    local active_sessions=$(w -h 2>/dev/null | awk '{print $1}' | sort -u)

    if [ -n "$active_sessions" ]; then
        # Check if any active session is a whitelisted user or root
        for session_user in $active_sessions; do
            if [ "$session_user" = "root" ] || is_whitelisted_user "$session_user"; then
                echo "active_admin_session:$session_user"
                return 0
            fi
        done
    fi

    # Check recent SSH logins in /var/log/secure
    if [ -f /var/log/secure ]; then
        local recent_admin=$(awk -v hours="$hours_ago" '
            BEGIN {
                cmd = "date -d \"" hours " hours ago\" +%s"
                cmd | getline threshold
                close(cmd)
            }
            /sshd.*Accepted/ && /root/ {
                timestamp = $1 " " $2 " " $3
                cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
                cmd | getline epoch
                close(cmd)

                if (epoch >= threshold) {
                    print "recent_admin_login:root"
                    exit
                }
            }
        ' /var/log/secure 2>/dev/null)

        if [ -n "$recent_admin" ]; then
            echo "$recent_admin"
            return 0
        fi
    fi

    echo "none"
    return 1
}

get_account_age_days() {
    local user=$1

    # Check home directory creation date as proxy for account age
    if [ -d "/home/$user" ]; then
        local home_created=$(stat -c %Y "/home/$user" 2>/dev/null)
        if [ -n "$home_created" ]; then
            local age_seconds=$(( $(date +%s) - home_created ))
            local age_days=$(( age_seconds / 86400 ))
            echo "$age_days"
            return 0
        fi
    fi

    # Fallback: Check /etc/passwd modification (less accurate)
    local stat_output=$(stat -c %Y /etc/passwd 2>/dev/null)
    if [ -z "$stat_output" ]; then
        echo "0"
        return 1
    fi
    local passwd_age=$(( $(date +%s) - stat_output ))
    local passwd_days=$(( passwd_age / 86400 ))
    echo "$passwd_days"
    return 0
}

check_who_made_change() {
    local file=$1
    local hours_ago=${2:-24}

    # Check audit logs for who modified the file
    if [ -f /var/log/audit/audit.log ]; then
        local audit_user=$(ausearch -f "$file" -ts recent 2>/dev/null | grep -oP 'acct="\K[^"]+' | head -1)
        if [ -n "$audit_user" ]; then
            echo "$audit_user"
            return 0
        fi
    fi

    # Fallback: Check /var/log/secure for context
    local secure_context=$(tail -1000 /var/log/secure 2>/dev/null | grep -E "useradd|usermod|passwd|chage" | tail -1 | awk '{print $5}' | cut -d'[' -f1)
    if [ -n "$secure_context" ]; then
        echo "$secure_context"
        return 0
    fi

    echo "unknown"
    return 1
}

#
# PHASE 2A FALSE POSITIVE REDUCTION - Additional correlation checks
#

check_tty_session() {
    local user=${1:-root}
    local timestamp=${2:-$(date +%s)}

    # Check if user has an active TTY/PTY session
    # Real admin sessions have TTY, automated scripts don't

    # Check currently logged in users
    local tty_info=$(w -h 2>/dev/null | awk -v user="$user" '$1 == user {print $2}')

    if [ -n "$tty_info" ]; then
        echo "tty-session:$tty_info"
        return 0
    fi

    # Check recent TTY allocations in /var/log/secure (within last hour)
    if [ -f /var/log/secure ]; then
        local recent_tty=$(awk -v user="$user" '
            /pam_unix.*session opened/ && $0 ~ user {
                if ($0 ~ /pts\/[0-9]+/) {
                    match($0, /pts\/[0-9]+/)
                    tty = substr($0, RSTART, RLENGTH)
                    print tty
                    exit
                }
            }
        ' /var/log/secure 2>/dev/null | tail -1)

        if [ -n "$recent_tty" ]; then
            echo "recent-tty:$recent_tty"
            return 0
        fi
    fi

    echo "no-tty"
    return 1
}

check_recent_login() {
    local user=$1
    local event_time=${2:-$(date +%s)}

    # Check if user logged in within last 2 hours
    # If yes, their changes are likely legitimate

    if [ -z "$user" ]; then
        echo "unknown:0"
        return 1
    fi

    # Use 'last' command to get recent logins
    local last_login=$(last -F "$user" 2>/dev/null | head -1)

    if [ -z "$last_login" ] || echo "$last_login" | grep -q "^$"; then
        echo "no-login:0"
        return 1
    fi

    # Parse login time from last command output
    # Format: user pts/0 ip Mon Feb 3 14:30:00 2026 - 16:45:00 (2:15)
    local login_time=$(echo "$last_login" | awk '{
        # Extract timestamp: Mon Feb 3 14:30:00 2026
        month = $4
        day = $5
        time = $6
        year = $7

        # Convert to date command format
        timestamp = month " " day " " year " " time
        cmd = "date -d \"" timestamp "\" +%s 2>/dev/null"
        cmd | getline epoch
        close(cmd)

        if (epoch > 0) {
            print epoch
        }
    }')

    if [ -z "$login_time" ] || [ "$login_time" = "0" ]; then
        echo "no-login:0"
        return 1
    fi

    # Calculate hours since login
    local seconds_since=$(( event_time - login_time ))
    local hours_since=$(( seconds_since / 3600 ))

    # If negative or within last 2 hours, return as recent
    if [ "$hours_since" -lt 0 ] || [ "$hours_since" -le 2 ]; then
        local hours_display=$(echo "scale=1; $seconds_since / 3600" | bc 2>/dev/null || echo "$hours_since")
        echo "recent-login:${hours_display}h"
        return 0
    fi

    echo "old-login:${hours_since}h"
    return 1
}

check_package_ownership() {
    local file=$1

    # Check if file belongs to an installed package
    # Helps catch package operations not detected in logs

    if [ ! -f "$file" ] && [ ! -d "$file" ]; then
        echo "not-found"
        return 1
    fi

    # Try RPM-based systems (RHEL, CentOS, AlmaLinux, Rocky, Fedora)
    if command -v rpm >/dev/null 2>&1; then
        local pkg=$(rpm -qf "$file" 2>/dev/null)
        if [ $? -eq 0 ] && [ "$pkg" != "file $file is not owned by any package" ]; then
            # Extract just package name without version
            local pkg_name=$(echo "$pkg" | sed 's/-[0-9].*//')
            echo "pkg-owned:$pkg_name"
            return 0
        fi
    fi

    # Try DEB-based systems (Debian, Ubuntu)
    if command -v dpkg >/dev/null 2>&1; then
        local pkg=$(dpkg -S "$file" 2>/dev/null | cut -d: -f1)
        if [ -n "$pkg" ]; then
            echo "pkg-owned:$pkg"
            return 0
        fi
    fi

    echo "not-owned"
    return 1
}

check_maintenance_mode() {
    # Check for various maintenance mode indicators

    local indicators=""

    # Check for /etc/nologin (standard maintenance file)
    if [ -f /etc/nologin ]; then
        indicators="${indicators}nologin "
    fi

    # Check for custom maintenance flags
    if [ -f /var/run/maintenance.flag ]; then
        indicators="${indicators}maintenance.flag "
    fi

    if [ -f /root/.maintenance ]; then
        indicators="${indicators}root-maintenance "
    fi

    # Check cPanel maintenance mode
    if [ -f /usr/local/cpanel/bin/whmapi1 ]; then
        local cpanel_maint=$(whmapi1 get_tweaksetting key=maintenance_mode 2>/dev/null | grep -A1 "value:" | tail -1 | awk '{print $2}')
        if [ "$cpanel_maint" = "1" ]; then
            indicators="${indicators}cpanel-maint "
        fi
    fi

    # Check /etc/motd or /etc/issue for maintenance notices
    if grep -qi "maintenance" /etc/motd 2>/dev/null; then
        indicators="${indicators}motd-notice "
    fi

    if grep -qi "maintenance" /etc/issue 2>/dev/null; then
        indicators="${indicators}issue-notice "
    fi

    if [ -n "$indicators" ]; then
        echo "maintenance-mode:$(echo $indicators | sed 's/ $//')"
        return 0
    fi

    echo "no-maintenance"
    return 1
}

#
# COMPROMISE DETECTION - Check for actual root compromise indicators
#

check_recent_password_changes() {
    echo "  Checking for recent password changes..." >&2

    local findings=""
    local risk=0
    local details=""

    # Check for password changes in last 7 days (using chage)
    # Password change date is stored in /etc/shadow field 3 (days since epoch)
    local recent_pw_changes=$(awk -F: -v cutoff=$(( $(date +%s) / 86400 - 7 )) '
        $3 != "" && $3 !~ /^!/ && $3 > cutoff {
            # Field 3 = last password change (days since 1970-01-01)
            print $1 ":" $3
        }
    ' /etc/shadow 2>/dev/null)

    if [ -n "$recent_pw_changes" ]; then
        local pw_count=$(echo "$recent_pw_changes" | wc -l)
        local pw_users=$(echo "$recent_pw_changes" | cut -d: -f1 | tr '\n' ',' | sed 's/,$//')

        # FALSE POSITIVE REDUCTION: Filter out whitelisted users
        local filtered_users=""
        local filtered_count=0
        for user in $(echo "$pw_users" | tr ',' ' '); do
            if ! is_whitelisted_user "$user" && ! is_ignored_user "$user"; then
                filtered_users="${filtered_users}${user},"
                filtered_count=$((filtered_count + 1))
            fi
        done
        filtered_users=${filtered_users%,}  # Remove trailing comma

        # If all users are whitelisted, skip
        if [ "$filtered_count" -eq 0 ]; then
            details="${details}(all-whitelisted) "
            echo "$risk|$findings$details"
            return 0
        fi

        # Check if admin is actively logged in (reduce risk)
        local admin_session=$(check_active_admin_session 1)
        local admin_active=0
        if [ "$admin_session" != "none" ]; then
            admin_active=1
            details="${details}[$admin_session] "
        fi

        # PHASE 2A: Check for TTY session (real terminal vs automated)
        local tty_session=$(check_tty_session "root")
        local has_tty=0
        if [[ "$tty_session" =~ ^tty-session: ]] || [[ "$tty_session" =~ ^recent-tty: ]]; then
            has_tty=1
            details="${details}[$tty_session] "
        fi

        # PHASE 2A: Check for recent login (within 2 hours)
        local recent_login=$(check_recent_login "root")
        local login_recent=0
        if [[ "$recent_login" =~ ^recent-login: ]]; then
            login_recent=1
            details="${details}[$recent_login] "
        fi

        # Check if in safe time window (reduce risk)
        local safe_window=0
        if is_safe_time_window; then
            safe_window=1
            details="${details}[safe-window] "
        fi

        # PHASE 2A: Check for maintenance mode
        local maint_mode=$(check_maintenance_mode)
        local in_maintenance=0
        if [[ "$maint_mode" =~ ^maintenance-mode: ]]; then
            in_maintenance=1
            details="${details}[$maint_mode] "
        fi

        # FALSE POSITIVE REDUCTION: Check if this is mass change (more suspicious)
        if [ "$filtered_count" -lt "$FP_PASSWORD_CHANGE_THRESHOLD" ]; then
            # Small number of password changes - likely legitimate
            # Only flag if root is included OR if outside business hours
            if echo "$filtered_users" | grep -q "root"; then
                findings="${findings}Root-Password-Changed "
                details="${details}(root) "

                # Calculate risk with context
                local base_risk=35
                # Reduce if admin active
                [ "$admin_active" -eq 1 ] && base_risk=$((base_risk - 15))
                # Reduce if business hours
                [ "$FP_IGNORE_BUSINESS_HOURS" = "yes" ] && is_business_hours && base_risk=$((base_risk - 10))
                # Reduce if safe window
                [ "$safe_window" -eq 1 ] && base_risk=$((base_risk - 10))
                # PHASE 2A: Reduce if TTY session present (real admin at terminal)
                [ "$has_tty" -eq 1 ] && base_risk=$((base_risk - 7))
                # PHASE 2A: Reduce if recent login (logged in within 2h)
                [ "$login_recent" -eq 1 ] && base_risk=$((base_risk - 8))
                # PHASE 2A: Reduce if maintenance mode
                [ "$in_maintenance" -eq 1 ] && base_risk=$((base_risk - 14))

                risk=$((risk + base_risk))
            elif [ "$filtered_count" -eq 1 ]; then
                # Single non-root password change
                local base_risk=5
                [ "$admin_active" -eq 1 ] && base_risk=2
                [ "$safe_window" -eq 1 ] && base_risk=2
                [ "$has_tty" -eq 1 ] && [ "$base_risk" -gt 1 ] && base_risk=$((base_risk - 1))
                [ "$login_recent" -eq 1 ] && [ "$base_risk" -gt 1 ] && base_risk=$((base_risk - 1))
                [ "$in_maintenance" -eq 1 ] && [ "$base_risk" -gt 1 ] && base_risk=$((base_risk - 1))
                risk=$((risk + base_risk))
                details="${details}Single-user:$filtered_users "
            else
                # 2-4 password changes, no root
                local base_risk=10
                [ "$admin_active" -eq 1 ] && base_risk=5
                [ "$safe_window" -eq 1 ] && base_risk=5
                [ "$has_tty" -eq 1 ] && base_risk=$((base_risk - 2))
                [ "$login_recent" -eq 1 ] && base_risk=$((base_risk - 2))
                [ "$in_maintenance" -eq 1 ] && base_risk=$((base_risk - 3))
                risk=$((risk + base_risk))
                details="${details}$filtered_count-users:$filtered_users "
            fi
        else
            # Mass password change (5+ accounts) - VERY suspicious
            findings="${findings}Mass-Password-Changes:$filtered_count-accounts "
            details="${details}Users:$filtered_users "
            # Even with admin active, mass changes are suspicious
            local base_risk=45
            [ "$admin_active" -eq 1 ] && base_risk=$((base_risk - 10))
            # PHASE 2A: Reduce slightly if TTY/login/maintenance (still suspicious, but less)
            [ "$has_tty" -eq 1 ] && base_risk=$((base_risk - 5))
            [ "$login_recent" -eq 1 ] && base_risk=$((base_risk - 5))
            [ "$in_maintenance" -eq 1 ] && base_risk=$((base_risk - 8))
            risk=$((risk + base_risk))
        fi
    fi

    # Check for locked accounts that were recently unlocked
    local recently_unlocked=$(awk -F: -v cutoff=$(( $(date +%s) / 86400 - 7 )) '
        # Field 2 starts with ! or !! = locked
        # If field 3 (last change) is recent and field 2 does NOT start with !, might have been unlocked
        $3 > cutoff && $2 !~ /^!/ && $2 != "" && $2 != "*" && $3 != "" {
            print $1
        }
    ' /etc/shadow 2>/dev/null | while read user; do
        # Check if account was previously locked (this is imperfect without history)
        if grep "^$user:" /etc/passwd | grep -q "/sbin/nologin\|/bin/false"; then
            echo "$user"
        fi
    done)

    if [ -n "$recently_unlocked" ]; then
        findings="${findings}Recently-Unlocked-Accounts:$(echo $recently_unlocked | tr '\n' ',') "
        risk=$((risk + 30))
    fi

    echo "$risk|$findings$details"
}

check_recent_user_changes() {
    echo "  Checking for recent user/group changes..." >&2

    local findings=""
    local risk=0

    # Check for users created in last 7 days (based on UID sequence)
    # In most systems, UIDs are assigned sequentially
    local max_uid=$(awk -F: '$3 >= 1000 && $3 < 60000 {print $3}' /etc/passwd | sort -n | tail -1)
    local recent_users=$(awk -F: -v max_uid="$max_uid" '
        $3 >= 1000 && $3 < 60000 && $3 >= (max_uid - 10) {
            print $1
        }
    ' /etc/passwd)

    if [ -n "$recent_users" ]; then
        # Check if these accounts are actually new (home dir creation date)
        local new_users=""
        local new_count=0
        for user in $recent_users; do
            if [ -d "/home/$user" ]; then
                local home_age=$(($(date +%s) - $(stat -c %Y /home/$user 2>/dev/null)))
                if [ "$home_age" -lt 604800 ]; then  # 7 days
                    local days=$((home_age / 86400))
                    new_users="${new_users}${user}(${days}d) "
                    new_count=$((new_count + 1))
                fi
            fi
        done

        if [ -n "$new_users" ]; then
            # FALSE POSITIVE REDUCTION: Filter out whitelisted/ignored users
            local filtered_new_users=""
            local filtered_new_count=0
            for user_entry in $new_users; do
                local username=$(echo "$user_entry" | cut -d'(' -f1)
                if ! is_whitelisted_user "$username" && ! is_ignored_user "$username"; then
                    filtered_new_users="${filtered_new_users}${user_entry} "
                    filtered_new_count=$((filtered_new_count + 1))
                fi
            done

            # If all users are whitelisted, skip
            if [ "$filtered_new_count" -eq 0 ]; then
                return 0
            fi

            # FALSE POSITIVE REDUCTION: Check if cPanel account creation
            local cpanel_activity=$(check_cpanel_account_creation 168)  # 7 days

            # Check if admin is actively logged in
            local admin_session=$(check_active_admin_session 24)
            local admin_active=0
            if [ "$admin_session" != "none" ]; then
                admin_active=1
            fi

            # PHASE 2A: Check for TTY session, recent login, maintenance mode
            local tty_session=$(check_tty_session "root")
            local has_tty=0
            [[ "$tty_session" =~ ^tty-session: ]] || [[ "$tty_session" =~ ^recent-tty: ]] && has_tty=1

            local recent_login=$(check_recent_login "root")
            local login_recent=0
            [[ "$recent_login" =~ ^recent-login: ]] && login_recent=1

            local maint_mode=$(check_maintenance_mode)
            local in_maintenance=0
            [[ "$maint_mode" =~ ^maintenance-mode: ]] && in_maintenance=1

            if [ "$cpanel_activity" = "cpanel_account_creation" ] && [ "$filtered_new_count" -le 3 ]; then
                # Likely legitimate cPanel hosting account
                findings="${findings}New-Users:$filtered_new_users[cpanel] "
                risk=$((risk + 5))  # Very low risk
            else
                # Not from cPanel or too many accounts
                findings="${findings}Recently-Created-Users:$filtered_new_users "
                if [ "$filtered_new_count" -eq 1 ]; then
                    # Single user creation
                    local base_risk=15
                    [ "$admin_active" -eq 1 ] && base_risk=8
                    is_business_hours && base_risk=$((base_risk - 3))
                    # PHASE 2A: Additional reductions
                    [ "$has_tty" -eq 1 ] && base_risk=$((base_risk - 3))
                    [ "$login_recent" -eq 1 ] && base_risk=$((base_risk - 3))
                    [ "$in_maintenance" -eq 1 ] && base_risk=$((base_risk - 4))
                    risk=$((risk + base_risk))
                else
                    # Multiple users
                    local base_risk=25
                    [ "$admin_active" -eq 1 ] && base_risk=15
                    # PHASE 2A: Additional reductions
                    [ "$has_tty" -eq 1 ] && base_risk=$((base_risk - 4))
                    [ "$login_recent" -eq 1 ] && base_risk=$((base_risk - 4))
                    [ "$in_maintenance" -eq 1 ] && base_risk=$((base_risk - 5))
                    risk=$((risk + base_risk))
                fi
            fi
        fi
    fi

    # Check for users added to sudo/wheel group recently
    local sudo_group=$(getent group sudo wheel 2>/dev/null | head -1)
    if [ -n "$sudo_group" ]; then
        local sudo_members=$(echo "$sudo_group" | cut -d: -f4)
        if [ -n "$sudo_members" ]; then
            # Check if group file was modified recently
            local group_age=$(($(date +%s) - $(stat -c %Y /etc/group 2>/dev/null)))
            if [ "$group_age" -lt 86400 ]; then
                findings="${findings}Sudo-Group-Modified-Recently:members=$sudo_members "
                risk=$((risk + 30))
            fi
        fi
    fi

    echo "$risk|$findings"
}

check_backdoor_accounts() {
    echo "  Checking for backdoor user accounts..." >&2

    local findings=""
    local risk=0

    # Check for multiple UID 0 accounts (besides root)
    local uid0_accounts=$(awk -F: '$3 == 0 && $1 != "root" {print $1}' /etc/passwd)
    if [ -n "$uid0_accounts" ]; then
        findings="${findings}Unauthorized-UID-0-Accounts:$(echo $uid0_accounts | tr '\n' ',') "
        risk=$((risk + 50))
    fi

    # Check for accounts with no password (empty password field, not locked)
    local no_pass=$(awk -F: '$2 == "" || $2 == " " {print $1}' /etc/shadow 2>/dev/null | head -10)
    if [ -n "$no_pass" ]; then
        findings="${findings}No-Password-Accounts:$(echo $no_pass | tr '\n' ',' | head -c 100) "
        risk=$((risk + 30))
    fi

    # Check for suspicious usernames (common backdoor names)
    local suspicious_users=$(awk -F: '
        $1 ~ /^(test|temp|backup|hacker|admin|ftpuser|nobody2|bin2|daemon2)$/ && $3 >= 1000 {
            print $1
        }
    ' /etc/passwd)

    if [ -n "$suspicious_users" ]; then
        # Filter out whitelisted users
        local filtered_suspicious=""
        for user in $suspicious_users; do
            if ! is_whitelisted_user "$user" && ! is_ignored_user "$user"; then
                # Check account age - old accounts less suspicious
                local account_age=$(get_account_age_days "$user")
                if [ "$account_age" -lt "$FP_MIN_ACCOUNT_AGE_DAYS" ]; then
                    # New account with suspicious name - HIGH risk
                    filtered_suspicious="${filtered_suspicious}${user}(${account_age}d),"
                elif [ "$account_age" -lt 365 ]; then
                    # Moderately old account - MEDIUM risk
                    filtered_suspicious="${filtered_suspicious}${user}(${account_age}d),"
                    # Lower risk for older accounts
                fi
                # Very old accounts (1+ year) with suspicious names ignored - likely legitimate
            fi
        done

        if [ -n "$filtered_suspicious" ]; then
            findings="${findings}Suspicious-Usernames:${filtered_suspicious%,} "
            # Risk based on newest account
            local min_age=999
            for user in $suspicious_users; do
                local age=$(get_account_age_days "$user")
                [ "$age" -lt "$min_age" ] && min_age=$age
            done

            if [ "$min_age" -lt 7 ]; then
                risk=$((risk + 30))  # Very new suspicious account
            elif [ "$min_age" -lt 30 ]; then
                risk=$((risk + 20))  # Recent suspicious account
            else
                risk=$((risk + 10))  # Older but still flagged
            fi
        fi
    fi

    echo "$risk|$findings"
}

check_unauthorized_ssh_keys() {
    echo "  Checking for unauthorized SSH keys..." >&2

    local findings=""
    local risk=0

    # Check root's authorized_keys
    if [ -f /root/.ssh/authorized_keys ]; then
        # FALSE POSITIVE REDUCTION: Only count active keys (not commented/disabled)
        local key_count=$(grep -v "^#" /root/.ssh/authorized_keys 2>/dev/null | grep -v "^$" | grep -c "ssh-")

        # Use configurable threshold
        if [ "$key_count" -gt "$FP_SSH_KEY_THRESHOLD" ]; then
            findings="${findings}Excessive-Root-SSH-Keys:$key_count "
            risk=$((risk + 20))
        fi

        # Check for keys with suspicious comments
        local suspicious_keys=$(grep -v "^#" /root/.ssh/authorized_keys 2>/dev/null | grep -i "hacker\|backdoor\|pwned\|rooted")
        if [ -n "$suspicious_keys" ]; then
            findings="${findings}Suspicious-SSH-Key-Comments "
            risk=$((risk + 40))
        fi

        # Check file permissions (should be 600)
        local perms=$(stat -c %a /root/.ssh/authorized_keys 2>/dev/null)
        if [ "$perms" != "600" ] && [ "$perms" != "400" ]; then
            findings="${findings}Incorrect-SSH-Key-Permissions:$perms "
            risk=$((risk + 15))
        fi
    fi

    # Check for authorized_keys in unusual locations
    local unusual_keys=$(find /tmp /var/tmp /dev/shm -name "authorized_keys" 2>/dev/null)
    if [ -n "$unusual_keys" ]; then
        findings="${findings}SSH-Keys-In-Unusual-Locations "
        risk=$((risk + 35))
    fi

    echo "$risk|$findings"
}

check_system_file_tampering() {
    echo "  Checking for system file tampering..." >&2

    local findings=""
    local risk=0

    # FALSE POSITIVE REDUCTION: Check if package manager was active
    local pkg_activity=""
    if [ "$FP_CHECK_PACKAGE_LOGS" = "yes" ]; then
        pkg_activity=$(check_package_manager_activity 24)
    fi

    # Check if admin was active (reduce suspicion)
    local admin_session=$(check_active_admin_session 24)
    local admin_active=0
    if [ "$admin_session" != "none" ]; then
        admin_active=1
    fi

    # Check if in safe time window
    local safe_window=0
    if is_safe_time_window; then
        safe_window=1
    fi

    # PHASE 2A: Check TTY, recent login, maintenance mode
    local tty_session=$(check_tty_session "root")
    local has_tty=0
    [[ "$tty_session" =~ ^tty-session: ]] || [[ "$tty_session" =~ ^recent-tty: ]] && has_tty=1

    local recent_login=$(check_recent_login "root")
    local login_recent=0
    [[ "$recent_login" =~ ^recent-login: ]] && login_recent=1

    local maint_mode=$(check_maintenance_mode)
    local in_maintenance=0
    [[ "$maint_mode" =~ ^maintenance-mode: ]] && in_maintenance=1

    # Check /etc/passwd modification time (recent changes suspicious)
    local passwd_age=$(($(date +%s) - $(stat -c %Y /etc/passwd 2>/dev/null)))
    if [ "$passwd_age" -lt 86400 ]; then  # Modified in last 24 hours
        local passwd_hours=$((passwd_age / 3600))

        # PHASE 2A: Check package ownership
        local pkg_owned=$(check_package_ownership "/etc/passwd")
        local is_pkg_owned=0
        [[ "$pkg_owned" =~ ^pkg-owned: ]] && is_pkg_owned=1

        # Build context string
        local context=""
        [ "$pkg_activity" != "none" ] && context="${context}$pkg_activity,"
        [ "$admin_active" -eq 1 ] && context="${context}admin-active,"
        [ "$safe_window" -eq 1 ] && context="${context}safe-window,"
        [ "$has_tty" -eq 1 ] && context="${context}tty-session,"
        [ "$login_recent" -eq 1 ] && context="${context}recent-login,"
        [ "$in_maintenance" -eq 1 ] && context="${context}maintenance,"
        [ "$is_pkg_owned" -eq 1 ] && context="${context}$pkg_owned,"
        context=${context%,}  # Remove trailing comma

        # Calculate risk
        local base_risk=25
        if [ "$pkg_activity" != "none" ]; then
            base_risk=5  # Package manager activity
        elif [ "$admin_active" -eq 1 ]; then
            base_risk=12  # Admin was logged in
        fi
        [ "$safe_window" -eq 1 ] && base_risk=$((base_risk / 2))
        # PHASE 2A: Additional reductions
        [ "$has_tty" -eq 1 ] && base_risk=$((base_risk - 3))
        [ "$login_recent" -eq 1 ] && base_risk=$((base_risk - 3))
        [ "$in_maintenance" -eq 1 ] && base_risk=$((base_risk - 5))
        [ "$is_pkg_owned" -eq 1 ] && base_risk=$((base_risk - 4))
        # Ensure minimum risk
        [ "$base_risk" -lt 0 ] && base_risk=0

        if [ -n "$context" ]; then
            findings="${findings}/etc/passwd-Modified-${passwd_hours}h-ago[$context] "
        else
            findings="${findings}/etc/passwd-Modified-${passwd_hours}h-ago "
        fi
        risk=$((risk + base_risk))
    fi

    # Check /etc/shadow modification time
    local shadow_age=$(($(date +%s) - $(stat -c %Y /etc/shadow 2>/dev/null)))
    if [ "$shadow_age" -lt 86400 ]; then
        local shadow_hours=$((shadow_age / 3600))

        # PHASE 2A: Check package ownership
        local pkg_owned_shadow=$(check_package_ownership "/etc/shadow")
        local is_pkg_owned_shadow=0
        [[ "$pkg_owned_shadow" =~ ^pkg-owned: ]] && is_pkg_owned_shadow=1

        # Build context string for shadow
        local context_shadow=""
        [ "$pkg_activity" != "none" ] && context_shadow="${context_shadow}$pkg_activity,"
        [ "$admin_active" -eq 1 ] && context_shadow="${context_shadow}admin-active,"
        [ "$safe_window" -eq 1 ] && context_shadow="${context_shadow}safe-window,"
        [ "$has_tty" -eq 1 ] && context_shadow="${context_shadow}tty-session,"
        [ "$login_recent" -eq 1 ] && context_shadow="${context_shadow}recent-login,"
        [ "$in_maintenance" -eq 1 ] && context_shadow="${context_shadow}maintenance,"
        [ "$is_pkg_owned_shadow" -eq 1 ] && context_shadow="${context_shadow}$pkg_owned_shadow,"
        context_shadow=${context_shadow%,}

        local base_risk=25
        if [ "$pkg_activity" != "none" ]; then
            base_risk=5
        elif [ "$admin_active" -eq 1 ]; then
            base_risk=12
        fi
        [ "$safe_window" -eq 1 ] && base_risk=$((base_risk / 2))
        # PHASE 2A: Additional reductions
        [ "$has_tty" -eq 1 ] && base_risk=$((base_risk - 3))
        [ "$login_recent" -eq 1 ] && base_risk=$((base_risk - 3))
        [ "$in_maintenance" -eq 1 ] && base_risk=$((base_risk - 5))
        [ "$is_pkg_owned_shadow" -eq 1 ] && base_risk=$((base_risk - 4))
        [ "$base_risk" -lt 0 ] && base_risk=0

        if [ -n "$context_shadow" ]; then
            findings="${findings}/etc/shadow-Modified-${shadow_hours}h-ago[$context_shadow] "
        else
            findings="${findings}/etc/shadow-Modified-${shadow_hours}h-ago "
        fi
        risk=$((risk + base_risk))
    fi

    # Check /etc/group modification time
    local group_age=$(($(date +%s) - $(stat -c %Y /etc/group 2>/dev/null)))
    if [ "$group_age" -lt 86400 ]; then
        local group_hours=$((group_age / 3600))

        # PHASE 2A: Check package ownership
        local pkg_owned_group=$(check_package_ownership "/etc/group")
        local is_pkg_owned_group=0
        [[ "$pkg_owned_group" =~ ^pkg-owned: ]] && is_pkg_owned_group=1

        # Build context string for group
        local context_group=""
        [ "$pkg_activity" != "none" ] && context_group="${context_group}$pkg_activity,"
        [ "$admin_active" -eq 1 ] && context_group="${context_group}admin-active,"
        [ "$safe_window" -eq 1 ] && context_group="${context_group}safe-window,"
        [ "$has_tty" -eq 1 ] && context_group="${context_group}tty-session,"
        [ "$login_recent" -eq 1 ] && context_group="${context_group}recent-login,"
        [ "$in_maintenance" -eq 1 ] && context_group="${context_group}maintenance,"
        [ "$is_pkg_owned_group" -eq 1 ] && context_group="${context_group}$pkg_owned_group,"
        context_group=${context_group%,}

        local base_risk=20
        if [ "$pkg_activity" != "none" ]; then
            base_risk=3
        elif [ "$admin_active" -eq 1 ]; then
            base_risk=10
        fi
        [ "$safe_window" -eq 1 ] && base_risk=$((base_risk / 2))
        # PHASE 2A: Additional reductions
        [ "$has_tty" -eq 1 ] && base_risk=$((base_risk - 2))
        [ "$login_recent" -eq 1 ] && base_risk=$((base_risk - 2))
        [ "$in_maintenance" -eq 1 ] && base_risk=$((base_risk - 4))
        [ "$is_pkg_owned_group" -eq 1 ] && base_risk=$((base_risk - 3))
        [ "$base_risk" -lt 0 ] && base_risk=0

        if [ -n "$context_group" ]; then
            findings="${findings}/etc/group-Modified-${group_hours}h-ago[$context_group] "
        else
            findings="${findings}/etc/group-Modified-${group_hours}h-ago "
        fi
        risk=$((risk + base_risk))
    fi

    # Check /etc/gshadow modification time
    if [ -f /etc/gshadow ]; then
        local gshadow_age=$(($(date +%s) - $(stat -c %Y /etc/gshadow 2>/dev/null)))
        if [ "$gshadow_age" -lt 86400 ]; then
            local gshadow_hours=$((gshadow_age / 3600))

            local base_risk=20
            if [ "$pkg_activity" != "none" ]; then
                base_risk=3
            elif [ "$admin_active" -eq 1 ]; then
                base_risk=10
            fi
            [ "$safe_window" -eq 1 ] && base_risk=$((base_risk / 2))

            if [ -n "$context" ]; then
                findings="${findings}/etc/gshadow-Modified-${gshadow_hours}h-ago[$context] "
            else
                findings="${findings}/etc/gshadow-Modified-${gshadow_hours}h-ago "
            fi
            risk=$((risk + base_risk))
        fi
    fi

    # Check for suspicious entries in /etc/passwd (exclude system accounts)
    # Look for non-standard shells on user accounts (UID >= 1000)
    local backdoor_shells=$(awk -F: '$3 >= 1000 && $7 != "" {
        shell = $7
        # Standard shells
        if (shell ~ /\/bash$/ || shell ~ /\/sh$/ || shell ~ /nologin$/ || shell ~ /false$/ || shell ~ /true$/) next
        # System accounts
        if ($1 == "sync" || $1 == "shutdown" || $1 == "halt" || $1 == "operator") next
        # cPanel shells
        if (shell ~ /\/noshell$/ || shell ~ /\/jailshell$/) next
        # If we get here, shell is suspicious
        print $1":"shell
    }' /etc/passwd 2>/dev/null)
    if [ -n "$backdoor_shells" ]; then
        findings="${findings}Suspicious-Login-Shells:$backdoor_shells "
        risk=$((risk + 30))
    fi

    # Check sudoers for unauthorized entries
    if [ -f /etc/sudoers ]; then
        local suspicious_sudo=$(grep -v "^#" /etc/sudoers 2>/dev/null | grep "NOPASSWD" | grep -v "root")
        if [ -n "$suspicious_sudo" ]; then
            findings="${findings}Suspicious-Sudoers-Entries "
            risk=$((risk + 35))
        fi
    fi

    echo "$risk|$findings"
}

check_suspicious_processes() {
    echo "  Checking for suspicious processes..." >&2

    local findings=""
    local risk=0

    # Check for processes with suspicious names
    local suspicious_procs=$(ps aux | grep -E "nc -l|ncat -l|/dev/tcp|bash -i|perl.*socket|python.*socket" | grep -v grep)
    if [ -n "$suspicious_procs" ]; then
        findings="${findings}Reverse-Shell-Processes "
        risk=$((risk + 50))
    fi

    # Check for hidden processes (spaces in name)
    local hidden_procs=$(ps aux | awk '$11 ~ /^[ ]+$/ {print $2}')
    if [ -n "$hidden_procs" ]; then
        findings="${findings}Hidden-Processes "
        risk=$((risk + 40))
    fi

    # Check for processes running from /tmp or /dev/shm
    local suspicious_tmp_procs=0
    local tmp_proc_pids=$(ps aux | awk '$11 ~ /\/(tmp|dev\/shm)/ {print $2}' 2>/dev/null)

    # FALSE POSITIVE REDUCTION: Check parent process
    for pid in $tmp_proc_pids; do
        local ppid=$(get_process_parent "$pid")
        if [ -n "$ppid" ] && ! is_legitimate_parent "$ppid"; then
            suspicious_tmp_procs=$((suspicious_tmp_procs + 1))
        fi
    done

    if [ "$suspicious_tmp_procs" -gt 0 ]; then
        findings="${findings}Suspicious-Processes-From-Tmp:$suspicious_tmp_procs "
        risk=$((risk + 30))
    fi

    # Check for unusual network connections
    local suspicious_conns=$(netstat -antp 2>/dev/null | grep ESTABLISHED | awk '{print $5}' | cut -d: -f1 | sort -u | wc -l)
    if [ "$suspicious_conns" -gt 50 ]; then
        findings="${findings}Excessive-Network-Connections:$suspicious_conns "
        risk=$((risk + 20))
    fi

    echo "$risk|$findings"
}

check_backdoor_cron_jobs() {
    echo "  Checking for backdoor cron jobs..." >&2

    local findings=""
    local risk=0

    # Check root crontab
    local suspicious_cron=$(crontab -l 2>/dev/null | grep -v "^#" | grep -E "wget|curl|nc |bash -i|/tmp/|/dev/shm|base64")
    if [ -n "$suspicious_cron" ]; then
        findings="${findings}Suspicious-Root-Cron-Jobs "
        risk=$((risk + 45))
    fi

    # Check /etc/cron.d for suspicious entries (exclude false positives)
    local suspicious_cron_d=$(grep -rE "wget.*\||curl.*\||bash -i|/dev/tcp" /etc/cron.d/ 2>/dev/null | grep -v "^#" | grep -v "cpanel\|license_sync")
    if [ -n "$suspicious_cron_d" ]; then
        findings="${findings}Suspicious-Cron.d-Entries "
        risk=$((risk + 45))
    fi

    # Check for cron jobs in unusual locations
    local unusual_crons=$(find /tmp /var/tmp /dev/shm -name "cron*" -o -name "*.cron" 2>/dev/null)
    if [ -n "$unusual_crons" ]; then
        findings="${findings}Cron-Jobs-In-Unusual-Locations "
        risk=$((risk + 40))
    fi

    echo "$risk|$findings"
}

check_bash_history_malicious_commands() {
    echo "  Analyzing bash history for malicious commands..." >&2

    local findings=""
    local risk=0

    if [ -f /root/.bash_history ]; then
        # Check for common attack commands (exclude legitimate installers)
        local malicious_cmds=$(grep -E "wget.*\/tmp\/.*sh|curl.*(base64|eval)|nc -l|bash -i.*\/dev\/tcp|chmod \+s \/|chattr \+i" /root/.bash_history 2>/dev/null | grep -v "claude.ai\|github.com\|githubusercontent")
        if [ -n "$malicious_cmds" ]; then
            findings="${findings}Malicious-Commands-In-History "
            risk=$((risk + 40))
        fi

        # Check for history clearing attempts
        local history_tampering=$(grep -E "history -c|rm.*bash_history|unset HISTFILE" /root/.bash_history 2>/dev/null)
        if [ -n "$history_tampering" ]; then
            findings="${findings}History-Tampering-Detected "
            risk=$((risk + 35))
        fi

        # Check for password hash modifications
        local passwd_mods=$(grep -E "echo.*\/etc\/passwd|echo.*\/etc\/shadow|vipw|usermod.*-p" /root/.bash_history 2>/dev/null)
        if [ -n "$passwd_mods" ]; then
            findings="${findings}Password-File-Manipulation "
            risk=$((risk + 45))
        fi
    fi

    # Check if history is disabled
    if ! grep -q "^HISTFILE=" /root/.bashrc 2>/dev/null && [ ! -f /root/.bash_history ]; then
        findings="${findings}Bash-History-Disabled "
        risk=$((risk + 25))
    fi

    echo "$risk|$findings"
}

check_web_shells() {
    echo "  Scanning for web shells..." >&2

    local findings=""
    local risk=0
    local web_roots=""

    # Determine web roots based on panel
    if [ -d /home ]; then
        web_roots="/home/*/public_html /var/www/html /usr/local/apache/htdocs"
    fi

    # FALSE POSITIVE REDUCTION: Only scan very recent files (last 7 days) with suspicious patterns
    # Look for multiple suspicious indicators, not just one function
    local suspicious_files=$(find $web_roots -type f -name "*.php" -mtime -7 2>/dev/null | head -50 | xargs grep -l "eval.*base64\|system.*base64\|exec.*\$_\|shell_exec.*POST\|assert.*base64" 2>/dev/null | head -10)

    if [ -n "$suspicious_files" ]; then
        local file_count=0

        # Check each file more carefully
        for file in $suspicious_files; do
            local file_age=$(($(date +%s) - $(stat -c %Y "$file" 2>/dev/null)))
            local file_days=$((file_age / 86400))

            # Very recent files (< 24 hours) are more suspicious
            if [ "$file_days" -lt 1 ]; then
                file_count=$((file_count + 1))
            elif [ "$file_days" -lt 3 ]; then
                # 1-3 days old, check for obfuscation
                if grep -q "base64_decode.*base64_decode\|eval.*eval\|gzinflate" "$file" 2>/dev/null; then
                    file_count=$((file_count + 1))
                fi
            fi
        done

        if [ "$file_count" -gt 0 ]; then
            findings="${findings}Potential-Web-Shells:$file_count "
            risk=$((risk + 35))
        fi
    fi

    # Check for suspicious PHP files in unusual locations
    local unusual_php=$(find /tmp /var/tmp /dev/shm -name "*.php" 2>/dev/null)
    if [ -n "$unusual_php" ]; then
        findings="${findings}PHP-Files-In-Tmp "
        risk=$((risk + 40))
    fi

    echo "$risk|$findings"
}

check_rootkit_indicators() {
    echo "  Checking for rootkit indicators..." >&2

    local findings=""
    local risk=0

    # Check for common rootkit files
    local rootkit_files="/dev/.hid /usr/bin/.sniffer /usr/local/hide /lib/libproc.a"
    for file in $rootkit_files; do
        if [ -e "$file" ]; then
            findings="${findings}Rootkit-File:$file "
            risk=$((risk + 50))
        fi
    done

    # Check for suspicious kernel modules
    local suspicious_modules=$(lsmod | grep -E "^(diamond|phalanx|beastkit)")
    if [ -n "$suspicious_modules" ]; then
        findings="${findings}Suspicious-Kernel-Modules "
        risk=$((risk + 50))
    fi

    # Check for modified binaries (ls, ps, netstat) - look for backdoor/rootkit strings only
    for cmd in /bin/ls /bin/ps /bin/netstat; do
        if [ -f "$cmd" ]; then
            local strings_check=$(strings "$cmd" 2>/dev/null | grep -iE "backdoor|rootkit|\bhidden\b.*process|\bhide\b.*file")
            if [ -n "$strings_check" ]; then
                findings="${findings}Modified-Binary:$cmd "
                risk=$((risk + 50))
            fi
        fi
    done

    # Check for hidden directories (... or .  or . )
    local hidden_dirs=$(find / -maxdepth 3 -type d -name "..." -o -name ".  " -o -name ". " 2>/dev/null)
    if [ -n "$hidden_dirs" ]; then
        findings="${findings}Hidden-Directories "
        risk=$((risk + 35))
    fi

    echo "$risk|$findings"
}

check_suspicious_network_activity() {
    echo "  Analyzing network connections..." >&2

    local findings=""
    local risk=0

    # Check for connections to unusual ports (reverse shells often use 4444, 5555, 6666, 1337)
    local suspicious_ports=$(netstat -antp 2>/dev/null | grep ESTABLISHED | awk '{print $4}' | cut -d: -f2 | grep -E "^(4444|5555|6666|1337|31337)$")
    if [ -n "$suspicious_ports" ]; then
        findings="${findings}Suspicious-Port-Connections "
        risk=$((risk + 45))
    fi

    # Check for IRC connections (common in botnets)
    local irc_conns=$(netstat -antp 2>/dev/null | grep ESTABLISHED | grep ":6667\|:6666\|:7000")
    if [ -n "$irc_conns" ]; then
        findings="${findings}IRC-Connections-Detected "
        risk=$((risk + 30))
    fi

    # Check for excessive outbound connections from web server
    if command -v pgrep &>/dev/null; then
        local httpd_conns=$(lsof -p $(pgrep -d, httpd 2>/dev/null) 2>/dev/null | grep -c ESTABLISHED)
        if [ "$httpd_conns" -gt 100 ]; then
            findings="${findings}Excessive-Web-Server-Connections:$httpd_conns "
            risk=$((risk + 25))
        fi
    fi

    echo "$risk|$findings"
}

perform_compromise_detection() {
    local ip=$1

    echo -e "  ${YELLOW}Running comprehensive compromise detection...${NC}" >&2
    echo "" >&2

    # Load baseline for comparison
    load_baseline

    local total_risk=0
    local all_findings=""
    local all_mitigations=""
    local evidence_items=0

    # Run all compromise checks (11 total checks now)
    local result=$(check_recent_password_changes)
    local check_risk=$(echo "$result" | cut -d'|' -f1)
    local check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_recent_user_changes)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_backdoor_accounts)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_unauthorized_ssh_keys)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_system_file_tampering)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_suspicious_processes)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_backdoor_cron_jobs)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_bash_history_malicious_commands)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_web_shells)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_rootkit_indicators)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    result=$(check_suspicious_network_activity)
    check_risk=$(echo "$result" | cut -d'|' -f1)
    check_findings=$(echo "$result" | cut -d'|' -f2-)
    total_risk=$((total_risk + check_risk))
    [ -n "$check_findings" ] && all_findings="${all_findings}${check_findings}"

    # FALSE POSITIVE REDUCTION: Adjust risk based on indicator count
    if [ "$FP_REQUIRE_MULTIPLE_INDICATORS" = "yes" ]; then
        # Count number of distinct indicators
        local indicator_count=0
        echo "$all_findings" | grep -q "Password" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "User" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "UID-0" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "SSH" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "Modified" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "Process" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "Cron" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "History" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "Shell" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "Rootkit" && indicator_count=$((indicator_count + 1))
        echo "$all_findings" | grep -q "Network" && indicator_count=$((indicator_count + 1))

        # If only 1 indicator and low risk, reduce further
        if [ "$indicator_count" -eq 1 ] && [ "$total_risk" -lt 50 ]; then
            total_risk=$((total_risk / 2))
            all_findings="${all_findings}[single-indicator:lowered-risk] "
        # If multiple indicators, this is more confidence - increase risk slightly
        elif [ "$indicator_count" -ge 3 ]; then
            total_risk=$((total_risk + 15))
            all_findings="${all_findings}[multiple-indicators:$indicator_count] "
        fi
    fi

    # Cap at 100
    [ "$total_risk" -gt 100 ] && total_risk=100

    # CONFIDENCE CALCULATION: Calculate how confident we are this is a real threat
    local confidence_result=$(calculate_confidence_score "$total_risk" "$all_findings" "$all_mitigations")
    local confidence_score=$(echo "$confidence_result" | cut -d'|' -f1)
    local confidence_level=$(echo "$confidence_result" | cut -d'|' -f2)
    local matched_patterns=$(echo "$confidence_result" | cut -d'|' -f3)

    # Update baseline with current state (for future comparisons)
    update_baseline

    # Return: risk|findings|confidence_score|confidence_level|patterns
    echo "$total_risk|$all_findings|$confidence_score|$confidence_level|$matched_patterns"
}

#
# AUTOMATED RESPONSE
#

trigger_automated_response() {
    local ip=$1
    local risk_score=${2:-0}
    local username=$3
    local panel=$4

    # Skip if risk_score is not a valid number
    if ! [[ "$risk_score" =~ ^[0-9]+$ ]]; then
        echo "Warning: Invalid risk_score '$risk_score', skipping automated response" >&2
        return 1
    fi

    # CRITICAL: 85-100
    if [ "$risk_score" -ge "$RISK_CRITICAL" ] && [ "$SUSPICIOUS_LOGIN_AUTO_BLOCK" = "yes" ]; then
        echo -e "\n${RED}🚨 CRITICAL RISK: Triggering automated response${NC}"

        # 1. Block IP
        if command -v csf &>/dev/null; then
            echo "  [1/3] Blocking IP via CSF..."
            if csf -d "$ip" "Suspicious login (risk: $risk_score)" 2>/dev/null; then
                echo -e "    ${GREEN}✓ IP blocked via CSF${NC}"
            else
                echo -e "    ${RED}✗ CSF block failed${NC}"
            fi
        else
            echo "  [1/3] Blocking IP via iptables..."
            if iptables -I INPUT -s "$ip" -j DROP 2>/dev/null; then
                echo -e "    ${GREEN}✓ IP blocked via iptables${NC}"
            else
                echo -e "    ${RED}✗ iptables block failed${NC}"
            fi
        fi

        # 2. Trigger rkhunter scan
        if [ "$SUSPICIOUS_LOGIN_AUTO_SCAN" = "yes" ] && [ -f "$MALWARE_SCANNER" ]; then
            echo "  [2/3] Triggering rootkit scan..."
            # Run in background with timeout
            timeout 300 bash "$MALWARE_SCANNER" --scanner rkhunter --quick &>/dev/null &
            local scan_pid=$!
            echo -e "    ${GREEN}✓ Rootkit scan initiated (PID: $scan_pid)${NC}"
        else
            echo "  [2/3] Rootkit scan (skipped - not configured)"
        fi

        # 3. CSI recommendation (cPanel only)
        if [ "$panel" = "cpanel" ]; then
            echo "  [3/3] CSI scan recommended"
            echo ""
            echo "    Run comprehensive security scan:"
            echo "    wget https://raw.githubusercontent.com/CpanelInc/tech-CSI/master/csi.pl"
            echo "    perl csi.pl --full"
        fi

    # HIGH: 70-84
    elif [ "$risk_score" -ge "$RISK_HIGH" ]; then
        echo -e "\n${YELLOW}⚠️  HIGH RISK: Manual review recommended${NC}"

        if [ "$SUSPICIOUS_LOGIN_AUTO_BLOCK" = "yes" ] && command -v csf &>/dev/null; then
            echo "  [1/2] Adding temporary rate limit..."
            if csf -tr "$ip" 300 "Rate limit: suspicious login" 2>/dev/null; then
                echo -e "    ${GREEN}✓ Rate limited for 5 minutes${NC}"
            fi
        fi

        echo "  [2/2] Schedule security scan for review"

    # MEDIUM: 50-69
    elif [ "$risk_score" -ge "$RISK_MEDIUM" ]; then
        echo -e "\n${BLUE}ℹ️  MEDIUM RISK: Monitoring recommended${NC}"

    # LOW: <50
    else
        echo -e "\n${GREEN}✓ LOW RISK: Logged for analysis${NC}"
    fi
}

#
# REPORTING
#

generate_report() {
    local panel=$1

    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
    echo -e "${CYAN}     SUSPICIOUS LOGIN MONITOR - Integrated Security Report${NC}"
    echo -e "${CYAN}     Generated: $(date '+%Y-%m-%d %H:%M:%S')${NC}"
    echo -e "${CYAN}     Scanning: Last $HOURS hours${NC}"
    echo -e "${CYAN}     Panel: $panel${NC}"
    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
    echo ""

    # Count total events
    local total_events=$(cat "$SSH_EVENTS" "$PANEL_EVENTS" 2>/dev/null | wc -l)
    local successful=$(cat "$SSH_EVENTS" "$PANEL_EVENTS" 2>/dev/null | grep -c "|success$")
    local failed=$(cat "$SSH_EVENTS" "$PANEL_EVENTS" 2>/dev/null | grep -c "|failed$")
    local root_count=$(cat "$SSH_EVENTS" "$PANEL_EVENTS" 2>/dev/null | grep -c "|root|")

    if [ ! -s "$SUSPICIOUS_IPS" ]; then
        echo -e "${GREEN}✓ No suspicious login activity detected${NC}"
        echo ""
        echo "SUMMARY:"
        echo "  Total Login Events: $total_events"
        echo "  Successful: $successful"
        echo "  Failed: $failed"
        echo "  Root Logins: $root_count"
        echo ""
        return 0
    fi

    local critical_count=$(awk -F'|' -v thresh=$RISK_CRITICAL '$2 >= thresh' "$SUSPICIOUS_IPS" | wc -l)
    local high_count=$(awk -F'|' -v crit=$RISK_CRITICAL -v high=$RISK_HIGH '$2 >= high && $2 < crit' "$SUSPICIOUS_IPS" | wc -l)

    if [ "$critical_count" -gt 0 ]; then
        echo -e "${RED}🚨 CRITICAL ALERTS ($critical_count):${NC}"
        echo ""

        awk -F'|' -v thresh=$RISK_CRITICAL '$2 >= thresh' "$SUSPICIOUS_IPS" | head -n 5 | while IFS='|' read -r ip risk reasons successful failed root users services; do
            echo -e "  ${RED}[CRITICAL] $ip - Risk: $risk/100${NC}"
            echo "      ┌─────────────────────────────────────────────────────────"
            echo "      │ LOGIN EVENT"
            echo "      ├─────────────────────────────────────────────────────────"
            echo "      │ IP: $ip"
            echo "      │ Successful logins: ${successful:-0}"
            echo "      │ Failed attempts: ${failed:-0}"
            echo "      │ Root logins: ${root:-0}"
            echo "      │ Users: $users"
            echo "      │ Services: $services"
            echo "      │ Initial Risk Factors: $reasons"
            echo "      │ Initial Risk: $risk/100"
            echo "      │"

            # Cross-reference with bot analyzer
            echo "      ├─────────────────────────────────────────────────────────"
            echo "      │ ACCESS LOG CORRELATION (bot-analyzer.sh)"
            echo "      ├─────────────────────────────────────────────────────────"
            local correlation=$(correlate_with_access_logs "$ip" "$risk")
            local corr_risk=$(echo "$correlation" | cut -d'|' -f1)
            local corr_attacks=$(echo "$correlation" | cut -d'|' -f2-)

            if [ "$corr_risk" != "0" ] && [ -n "$corr_attacks" ]; then
                echo "      │ ⚠️  Web attack activity detected:"
                for attack in $corr_attacks; do
                    echo "      │   - $attack"
                done
                risk=$((risk + corr_risk))
                [ "$risk" -gt 100 ] && risk=100
            else
                echo "      │ $corr_attacks"
            fi
            echo "      │"

            # Check IP reputation
            echo "      ├─────────────────────────────────────────────────────────"
            echo "      │ IP REPUTATION"
            echo "      ├─────────────────────────────────────────────────────────"
            local rep_result=$(check_ip_reputation "$ip" "$risk")
            local rep_risk=$(echo "$rep_result" | cut -d'|' -f1)
            local rep_notes=$(echo "$rep_result" | cut -d'|' -f2-)

            if [ "$rep_risk" != "0" ]; then
                echo "      │ $rep_notes"
                risk=$((risk + rep_risk))
                [ "$risk" -gt 100 ] && risk=100
            else
                echo "      │ $rep_notes"
            fi
            echo "      │"

            # Threat intelligence
            echo "      ├─────────────────────────────────────────────────────────"
            echo "      │ THREAT INTELLIGENCE"
            echo "      ├─────────────────────────────────────────────────────────"
            local threat_result=$(correlate_with_threat_intel "$ip")
            local threat_risk=$(echo "$threat_result" | cut -d'|' -f1)
            local threat_notes=$(echo "$threat_result" | cut -d'|' -f2-)

            if [ "$threat_risk" != "0" ]; then
                echo "      │ ⚠️  $threat_notes"
                risk=$((risk + threat_risk))
                [ "$risk" -gt 100 ] && risk=100
            else
                echo "      │ $threat_notes"
            fi

            echo "      │"

            # COMPROMISE DETECTION - Check if server is actually rooted
            echo "      ├─────────────────────────────────────────────────────────"
            echo -e "      │ ${RED}COMPROMISE DETECTION - System Integrity Check${NC}"
            echo "      ├─────────────────────────────────────────────────────────"
            local compromise_result=$(perform_compromise_detection "$ip")
            local compromise_risk=$(echo "$compromise_result" | cut -d'|' -f1)
            local compromise_findings=$(echo "$compromise_result" | cut -d'|' -f2-)

            if [ "$compromise_risk" -ge 50 ]; then
                echo -e "      │ ${RED}🚨 COMPROMISE CONFIRMED - $compromise_risk risk points${NC}"
                echo "      │"
                echo "      │ Indicators of compromise found:"
                # Parse and display findings
                for finding in $(echo "$compromise_findings" | tr ' ' '\n'); do
                    echo "      │   • $finding"
                done
                risk=$((risk + compromise_risk))
                [ "$risk" -gt 100 ] && risk=100
            elif [ "$compromise_risk" -gt 0 ]; then
                echo -e "      │ ${YELLOW}⚠️  Suspicious indicators found - $compromise_risk risk points${NC}"
                echo "      │"
                for finding in $(echo "$compromise_findings" | tr ' ' '\n'); do
                    echo "      │   • $finding"
                done
                risk=$((risk + compromise_risk))
                [ "$risk" -gt 100 ] && risk=100
            else
                echo -e "      │ ${GREEN}✓ No compromise indicators detected${NC}"
                echo "      │ System integrity checks passed"
            fi

            echo "      │"
            echo "      ├─────────────────────────────────────────────────────────"
            if [ "$compromise_risk" -ge 50 ]; then
                echo -e "      │ ${RED}FINAL RISK SCORE: $risk/100 - SERVER LIKELY COMPROMISED${NC}"
            else
                echo -e "      │ ${RED}FINAL RISK SCORE: $risk/100 - CRITICAL${NC}"
            fi
            echo "      └─────────────────────────────────────────────────────────"

            # Trigger automated response
            trigger_automated_response "$ip" "$risk" "$(echo "$users" | cut -d',' -f1)" "$panel"

            echo ""
        done
    fi

    if [ "$high_count" -gt 0 ]; then
        echo -e "${YELLOW}⚠️  HIGH ALERTS ($high_count):${NC}"
        echo ""

        awk -F'|' -v crit=$RISK_CRITICAL -v high=$RISK_HIGH '$2 >= high && $2 < crit' "$SUSPICIOUS_IPS" | head -n 5 | while IFS='|' read -r ip risk reasons successful failed root users services; do
            echo -e "  ${YELLOW}[HIGH] $ip - Risk: $risk/100${NC}"
            echo "      Successful: ${successful:-0} | Failed: ${failed:-0} | Root: ${root:-0}"
            echo "      Reasons: $reasons"

            # Quick correlation
            local correlation=$(correlate_with_access_logs "$ip" "$risk")
            local corr_attacks=$(echo "$correlation" | cut -d'|' -f2-)
            if [ -n "$corr_attacks" ] && [ "$corr_attacks" != "No access log activity" ]; then
                echo "      Web attacks: $corr_attacks"
            fi

            echo ""
        done
    fi

    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
    echo "SUMMARY:"
    echo ""
    echo "  Total Login Events: $total_events"
    echo "  Successful: $successful"
    echo "  Failed: $failed"
    echo "  Root Logins: $root_count"
    echo ""
    echo "  Suspicious IPs: $(wc -l < "$SUSPICIOUS_IPS")"
    echo "  Critical Risk: $critical_count"
    echo "  High Risk: $high_count"
    echo ""

    # Integration status
    echo "  Integration Status:"
    local bot_report=$(ls -t "$TOOLKIT_ROOT"/tmp/bot_analysis_report_*.txt /tmp/bot_analysis_report_*.txt 2>/dev/null | head -n1)
    [ -n "$bot_report" ] && echo "    ✓ Bot Analyzer: Available" || echo "    ✗ Bot Analyzer: No recent data"
    [ -f "$IP_REPUTATION_LIB" ] && echo "    ✓ IP Reputation: Available" || echo "    ✗ IP Reputation: Not available"
    [ -f "$THREAT_INTEL_LIB" ] && echo "    ✓ Threat Intelligence: Available" || echo "    ✗ Threat Intelligence: Not available"

    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
}

#
# MAIN
#

main() {
    echo -e "${CYAN}Starting Suspicious Login Monitor...${NC}"
    echo ""

    # Detect panel
    local panel=$(detect_panel)
    echo "Detected panel: $panel"
    echo ""

    # Parse logs (universal parsers first)
    parse_ssh_logins "$HOURS"
    parse_wtmp_logins "$HOURS"
    parse_btmp_logins "$HOURS"
    parse_sudo_escalation "$HOURS"

    # Parse panel-specific logs
    case "$panel" in
        cpanel)
            parse_cpanel_logins "$HOURS"
            ;;
        plesk)
            parse_plesk_logins "$HOURS"
            ;;
        interworx)
            parse_interworx_logins "$HOURS"
            ;;
    esac

    # Analyze
    detect_anomalies

    # Generate report
    generate_report "$panel" | tee "$REPORT_FILE"

    echo ""
    echo "Report saved to: $REPORT_FILE"

    # ALWAYS run system-wide compromise detection (regardless of login activity)
    echo ""
    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
    echo -e "${CYAN}     SYSTEM COMPROMISE DETECTION - Integrity Check${NC}"
    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
    echo ""

    # Show root password change date (always display)
    echo -e "${BLUE}Root Account Status:${NC}"
    if [ -f /etc/shadow ]; then
        local root_pw_date=$(awk -F: '$1 == "root" {print $3}' /etc/shadow 2>/dev/null)
        if [ -n "$root_pw_date" ] && [ "$root_pw_date" != "0" ]; then
            # Convert days since epoch to actual date
            local pw_date=$(date -d "1970-01-01 + $root_pw_date days" "+%Y-%m-%d" 2>/dev/null)
            local pw_age_days=$(( $(date +%s) / 86400 - root_pw_date ))

            echo "  Last password change: $pw_date ($pw_age_days days ago)"

            # Warn if password hasn't been changed in a long time or changed very recently
            if [ "$pw_age_days" -lt 1 ]; then
                echo -e "  ${RED}⚠️  Password changed TODAY - verify this was authorized${NC}"
            elif [ "$pw_age_days" -lt 7 ]; then
                echo -e "  ${YELLOW}⚠️  Password changed within last 7 days${NC}"
            elif [ "$pw_age_days" -gt 365 ]; then
                echo -e "  ${YELLOW}⚠️  Password not changed in over a year (consider rotating)${NC}"
            else
                echo "  Status: Normal"
            fi
        else
            echo -e "  ${RED}⚠️  Unable to determine password age${NC}"
        fi
    fi
    echo ""

    local compromise_result=$(perform_compromise_detection "system-wide")
    local compromise_risk=$(echo "$compromise_result" | cut -d'|' -f1)
    local compromise_findings=$(echo "$compromise_result" | cut -d'|' -f2)
    local confidence_score=$(echo "$compromise_result" | cut -d'|' -f3)
    local confidence_level=$(echo "$compromise_result" | cut -d'|' -f4)
    local matched_patterns=$(echo "$compromise_result" | cut -d'|' -f5-)

    if [ "$compromise_risk" -ge 100 ]; then
        echo -e "${RED}🚨 CRITICAL: Server shows strong indicators of compromise${NC}"
        echo -e "${RED}    Risk Score: $compromise_risk/100${NC}"
        echo -e "${RED}    Confidence: $confidence_level ($confidence_score/100)${NC}"
        [ -n "$matched_patterns" ] && echo -e "${RED}    Attack Patterns: $matched_patterns${NC}"
        echo ""
        echo "Indicators found:"
        for finding in $(echo "$compromise_findings" | tr ' ' '\n'); do
            echo -e "  ${RED}•${NC} $(echo $finding | tr '-' ' ')"
        done
        echo ""
        echo -e "${RED}RECOMMENDED ACTIONS:${NC}"
        echo "  1. Investigate all findings immediately"
        echo "  2. Run full rootkit scan: rkhunter --check"
        if [ "$panel" = "cpanel" ]; then
            echo "  3. Run cPanel CSI: perl csi.pl --full"
        fi
        echo "  4. Consider full system reinstall if compromised"
    elif [ "$compromise_risk" -ge 50 ]; then
        echo -e "${RED}⚠️  WARNING: Suspicious indicators detected${NC}"
        echo -e "${YELLOW}    Risk Score: $compromise_risk/100${NC}"
        echo -e "${YELLOW}    Confidence: $confidence_level ($confidence_score/100)${NC}"
        [ -n "$matched_patterns" ] && echo -e "${YELLOW}    Attack Patterns: $matched_patterns${NC}"
        echo ""
        echo "Indicators found:"
        for finding in $(echo "$compromise_findings" | tr ' ' '\n'); do
            echo -e "  ${YELLOW}•${NC} $(echo $finding | tr '-' ' ')"
        done
        echo ""
        echo -e "${YELLOW}RECOMMENDED ACTIONS:${NC}"
        if [ "$confidence_level" = "HIGH" ]; then
            echo "  1. HIGH confidence - Likely a real threat, investigate immediately"
            echo "  2. Run rootkit scan: rkhunter --check"
            echo "  3. Check for unauthorized access"
        elif [ "$confidence_level" = "LOW" ]; then
            echo "  1. LOW confidence - May be legitimate activity"
            echo "  2. Review context in findings (look for [brackets])"
            echo "  3. Consider whitelisting if this is normal for your environment"
        else
            echo "  1. Review all findings carefully"
            echo "  2. Run rootkit scan: rkhunter --check"
            echo "  3. Investigate recent account/file changes"
        fi
    elif [ "$compromise_risk" -gt 0 ]; then
        echo -e "${BLUE}ℹ️  NOTICE: Minor security concerns detected${NC}"
        echo -e "${BLUE}    Risk Score: $compromise_risk/100${NC}"
        echo -e "${BLUE}    Confidence: $confidence_level ($confidence_score/100)${NC}"
        [ -n "$matched_patterns" ] && echo -e "${BLUE}    Note: $matched_patterns${NC}"
        echo ""
        echo "Issues found:"
        for finding in $(echo "$compromise_findings" | tr ' ' '\n'); do
            echo -e "  ${BLUE}•${NC} $(echo $finding | tr '-' ' ')"
        done
        echo ""
        if [ "$confidence_level" = "LOW" ]; then
            echo "LOW confidence - Likely legitimate activity with context:"
            echo "  • Look for [admin-active], [yum_activity], [cpanel], etc. in findings"
            echo "  • These indicate known legitimate sources"
            echo "  • Review when convenient, no urgent action needed"
        else
            echo "Review these items when convenient."
        fi
    else
        echo -e "${GREEN}✓ No compromise indicators detected${NC}"
        echo -e "${GREEN}    Confidence: HIGH (100/100)${NC}"
        echo ""
        echo "System integrity checks:"
        echo "  ✓ No suspicious password changes detected"
        echo "  ✓ No suspicious user/group changes"
        echo "  ✓ No unauthorized UID 0 accounts"
        echo "  ✓ No suspicious SSH keys"
        echo "  ✓ No system file tampering detected"
        echo "  ✓ No suspicious processes found"
        echo "  ✓ No backdoor cron jobs"
        echo "  ✓ No malicious commands in bash history"
        echo "  ✓ No web shells detected"
        echo "  ✓ No rootkit indicators"
        echo "  ✓ No suspicious network activity"
    fi

    echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
}

# Run main function
main

exit 0
