#!/bin/bash

################################################################################
# Menu Functions Library
################################################################################
# Provides standardized menu display and input handling for all toolkit scripts
# No text colors - uses plain text for maximum compatibility
# Handles proper back/cancel navigation and input validation
#
# REQUIREMENTS:
#   - Bash 4.1 or later (uses ${var,,} lowercase expansion and negative array indexing)
#   - set -eo pipefail is REQUIRED for error handling
#
# WARNING: This library sets global variables MENU_STACK, MENU_HISTORY, and
# INTERACTIVE_MODE. Do not modify these directly - use provided functions.
################################################################################

set -eo pipefail

# Bash version check
if [ "${BASH_VERSINFO[0]}" -lt 4 ] || ([ "${BASH_VERSINFO[0]}" -eq 4 ] && [ "${BASH_VERSINFO[1]}" -lt 1 ]); then
    echo "[ERROR] menu-functions.sh requires Bash 4.1 or later (detected: ${BASH_VERSION})" >&2
    if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
        exit 1
    else
        return 1
    fi
fi

################################################################################
# MENU DISPLAY FUNCTIONS
################################################################################

# Display menu header with separator line
# Usage: menu_header "Menu Title"
menu_header() {
    local title="$1"
    echo ""
    echo "=========================================="
    echo "  $title"
    echo "=========================================="
    echo ""
}

# Display a single menu option with number and description
# Usage: menu_option 1 "First Option" "Optional description"
# Note: Handles long labels and descriptions with wrapping
menu_option() {
    local num="$1"
    local label="$2"
    local desc="$3"

    if [ -z "$desc" ]; then
        # Just label
        printf "  %d) %s\n" "$num" "$label"
    else
        # Label with description on same line
        printf "  %d) %-30s - %s\n" "$num" "$label" "$desc"
    fi
}

# Display option with long/wrapped description
# Usage: menu_option_wrapped 1 "Option" "This is a very long description that might wrap to multiple lines"
menu_option_wrapped() {
    local num="$1"
    local label="$2"
    local desc="$3"
    local width="${4:-70}"

    printf "  %d) %s\n" "$num" "$label"

    # Wrap description text
    if [ -n "$desc" ]; then
        # Indent wrapped text
        echo "$desc" | fold -w "$((width - 6))" -s | sed 's/^/      /'
    fi
}

# Display divider line
# Usage: menu_divider
menu_divider() {
    echo ""
    echo "=========================================="
}

# Display back/exit option
# Usage: menu_back "Main Menu"  (shows "0) Back to Main Menu")
# Usage: menu_back               (shows "0) Back")
menu_back() {
    local target="${1:-}"
    if [ -z "$target" ]; then
        printf "  %d) %s\n" 0 "Back"
    else
        printf "  %d) %s %s\n" 0 "Back to" "$target"
    fi
}

# Display exit option (for main menu only)
# Usage: menu_exit
menu_exit() {
    printf "  %d) %s\n" 0 "Exit"
}

################################################################################
# INPUT HANDLING FUNCTIONS
################################################################################

# Read menu choice from user with validation
# Usage: read_menu_choice "option" 0 5
#   Returns: choice in $MENU_CHOICE variable
#   Validates: input is numeric and in range [min, max]
read_menu_choice() {
    local prompt="${1:-Select option}"
    local min="${2:-0}"
    local max="${3:-}"

    # Check if interactive (has terminal)
    if [ ! -t 0 ] && [ -z "$INTERACTIVE_MODE" ]; then
        print_error "Menu requires interactive terminal (TTY)"
        return 1
    fi

    # If max not specified, only validate it's a number
    if [ -z "$max" ]; then
        while true; do
            printf "%s: " "$prompt"
            read -r MENU_CHOICE || return 1

            # Check if numeric
            if [[ "$MENU_CHOICE" =~ ^[0-9]+$ ]]; then
                return 0
            fi

            echo "Invalid input. Enter a number."
        done
    else
        # Validate range
        while true; do
            printf "%s (%d-%d): " "$prompt" "$min" "$max"
            read -r MENU_CHOICE || return 1

            # Check if numeric
            if ! [[ "$MENU_CHOICE" =~ ^[0-9]+$ ]]; then
                echo "Invalid input. Enter a number between $min and $max."
                continue
            fi

            # Check if in range
            if [ "$MENU_CHOICE" -ge "$min" ] && [ "$MENU_CHOICE" -le "$max" ]; then
                return 0
            fi

            echo "Invalid option. Enter a number between $min and $max."
        done
    fi
}

# Validate menu choice is in valid range
# Usage: validate_menu_choice 5 0 10
#   Returns: 0 if valid, 1 if invalid
validate_menu_choice() {
    local choice="$1"
    local min="${2:-0}"
    local max="$3"

    # Must be numeric
    if ! [[ "$choice" =~ ^[0-9]+$ ]]; then
        return 1
    fi

    # Check range
    if [ "$choice" -ge "$min" ] && [ "$choice" -le "$max" ]; then
        return 0
    fi

    return 1
}

################################################################################
# ERROR HANDLING FUNCTIONS
################################################################################

# Display invalid option message
# Usage: menu_invalid_choice
menu_invalid_choice() {
    echo "Invalid option. Please try again."
    sleep 1
}

# Display error for invalid input
# Usage: menu_input_error "Please enter a number"
menu_input_error() {
    local msg="${1:-Invalid input}"
    print_error "$msg"
    sleep 1
}

################################################################################
# COMPLETE MENU WRAPPER
################################################################################

# All-in-one menu display and input handler
# Usage: show_menu "Menu Title" "0" "Back to Main Menu" "option1" "option2" ...
# Returns choice in $MENU_CHOICE
#
# Example:
#   show_menu "Security Menu" "3" "Main Menu" \
#       "Bot Analyzer" \
#       "Malware Scanner" \
#       "IP Reputation Manager"
#   case "$MENU_CHOICE" in
#       1) run_bot_analyzer ;;
#       2) run_malware_scanner ;;
#       3) run_ip_reputation ;;
#       0) return ;;
#   esac
show_menu() {
    local title="$1"
    local max_option="$2"
    local back_target="$3"
    shift 3
    local options=("$@")

    # Display header
    menu_header "$title"

    # Display options
    for i in "${!options[@]}"; do
        menu_option $((i+1)) "${options[$i]}"
    done

    echo ""
    menu_back "$back_target"
    menu_divider

    # Read input
    read_menu_choice "Select option" 0 "$max_option"
}

################################################################################
# INTERACTIVE MODE DETECTION
################################################################################

# Detect if running in interactive mode
# Returns: 0 if interactive, 1 if not
# Sets: INTERACTIVE_MODE variable
detect_interactive_mode() {
    if [ -t 0 ]; then
        # Has TTY
        INTERACTIVE_MODE=1
        return 0
    fi

    # Check bash $- variable for 'i' flag
    if [[ "$-" == *i* ]]; then
        INTERACTIVE_MODE=1
        return 0
    fi

    # Not interactive
    INTERACTIVE_MODE=0
    return 1
}

################################################################################
# MENU LOOP HELPERS
################################################################################

# Standard menu loop skeleton
# Shows menu, reads input, validates range, returns choice
# Usage: (in your case statement)
#   while true; do
#       menu_loop "Menu Title" "0" "Back" option1 option2 option3
#       case "$MENU_CHOICE" in
#           1) action1 ;;
#           2) action2 ;;
#           3) action3 ;;
#           0) return ;;
#           *) menu_invalid_choice ;;
#       esac
#   done
menu_loop() {
    show_menu "$@"
}

# Validate and display invalid choice error
# Usage: if ! validate_menu_choice "$MENU_CHOICE" 0 3; then menu_invalid_choice; fi
show_invalid_choice() {
    menu_invalid_choice
}

################################################################################
# CONFIRMATION DIALOGS
################################################################################

# Yes/No confirmation menu
# Usage: confirm_action "Delete all logs?"
# Returns: 0 for yes, 1 for no
confirm_action() {
    local question="$1"
    local default="${2:-n}"  # y or n

    if [ ! -t 0 ]; then
        print_error "Confirmation requires interactive terminal"
        return 1
    fi

    echo ""
    printf "%s (y/n) [%s]: " "$question" "$default"

    # Read with error handling - return error if read fails (EOF/closed stdin)
    if ! read -r response; then
        echo ""
        print_error "Confirmation canceled (EOF)"
        return 1
    fi

    case "$response" in
        [yY]) return 0 ;;
        [nN]) return 1 ;;
        "")
            # Use default
            [ "$default" = "y" ] && return 0 || return 1
            ;;
        *)
            echo "Invalid response. Please enter 'y' or 'n'."
            return 1
            ;;
    esac
}

################################################################################
# OPTION DISPLAY HELPERS
################################################################################

# Display option with indentation (for nested options)
# Usage: menu_option_nested 1 "Nested Option"
menu_option_nested() {
    local num="$1"
    local label="$2"
    printf "    %d) %s\n" "$num" "$label"
}

# Display section header within menu (not main header)
# Usage: menu_section "Analysis Options"
menu_section() {
    local section="$1"
    echo ""
    echo "  $section:"
}

# Display option with status indicator
# Usage: menu_option_status 1 "Feature Name" "enabled"
menu_option_status() {
    local num="$1"
    local label="$2"
    local status="$3"
    printf "  %d) %-30s [%s]\n" "$num" "$label" "$status"
}

# Display disabled option (grayed out / not selectable)
# Usage: menu_option_disabled 5 "Advanced Options" "(requires admin)"
menu_option_disabled() {
    local num="$1"
    local label="$2"
    local reason="$3"
    if [ -z "$reason" ]; then
        printf "  %d) %s (disabled)\n" "$num" "$label"
    else
        printf "  %d) %s %s\n" "$num" "$label" "$reason"
    fi
}

# Automatically number and display multiple options
# Usage: menu_options "Option 1" "Option 2" "Option 3"
menu_options() {
    local counter=1
    for option in "$@"; do
        menu_option "$counter" "$option"
        ((counter++))
    done
}

# Display option with default indicator
# Usage: menu_option_default 1 "Use this" true
menu_option_default() {
    local num="$1"
    local label="$2"
    local is_default="${3:-false}"

    if [ "$is_default" = "true" ] || [ "$is_default" = "1" ]; then
        printf "  %d) %s [DEFAULT]\n" "$num" "$label"
    else
        printf "  %d) %s\n" "$num" "$label"
    fi
}

# Display multiple options with default
# Usage: menu_options_with_default "1" "Opt1" "Opt2" "Opt3"
menu_options_with_default() {
    local default_num="$1"
    shift
    local counter=1

    for option in "$@"; do
        if [ "$counter" = "$default_num" ]; then
            menu_option_default "$counter" "$option" true
        else
            menu_option_default "$counter" "$option" false
        fi
        ((counter++))
    done
}

# Display group of related options
# Usage: menu_group "Database Options" 1 "MySQL" "PostgreSQL" "MariaDB"
menu_group() {
    local group_name="$1"
    shift
    local start_num="$1"
    shift
    local options=("$@")

    menu_section "$group_name"
    local counter="$start_num"
    for option in "${options[@]}"; do
        menu_option_nested "$counter" "$option"
        ((counter++))
    done
}

################################################################################
# UTILITY FUNCTIONS
################################################################################

# Clear screen and show banner (common pattern)
# Usage: clear_and_banner
clear_and_banner() {
    clear
    show_banner
}

# Wait for user before continuing (already in common-functions.sh)
# This ensures consistency if called from here
menu_press_enter() {
    press_enter
}

# Display loading indicator
# Usage: menu_loading "Scanning logs"
menu_loading() {
    local msg="$1"
    printf "%s" "$msg"
    for i in {1..3}; do
        printf "."
        sleep 0.5
    done
    echo ""
}

################################################################################
# MENU STATE TRACKING
################################################################################

# Push menu onto stack
# Usage: menu_push "Security Menu"
# Maximum depth: 50 levels (prevents accidental memory issues in pathological nesting)
menu_push() {
    local menu_name="$1"
    local max_depth=50

    if [ ${#MENU_STACK[@]} -ge "$max_depth" ]; then
        print_error "Menu nesting too deep (max $max_depth levels)"
        return 1
    fi

    MENU_STACK+=("$menu_name")
}

# Pop menu from stack
# Usage: menu_pop
menu_pop() {
    if [ ${#MENU_STACK[@]} -gt 0 ]; then
        unset 'MENU_STACK[-1]'
    fi
}

# Get current menu name
# Usage: current_menu=$(menu_current)
menu_current() {
    local stack_len=${#MENU_STACK[@]}
    if [ "$stack_len" -gt 0 ]; then
        echo "${MENU_STACK[$((stack_len - 1))]}"
    else
        echo "Main Menu"
    fi
}

# Get parent menu name
# Usage: parent_menu=$(menu_parent)
menu_parent() {
    local stack_len=${#MENU_STACK[@]}
    if [ "$stack_len" -gt 1 ]; then
        echo "${MENU_STACK[$((stack_len - 2))]}"
    else
        echo "Main Menu"
    fi
}

################################################################################
# MENU HISTORY & LOGGING
################################################################################

# Log menu selection to history
# Usage: menu_log_selection "Bot Analyzer" 1
menu_log_selection() {
    local menu_name="$1"
    local choice="$2"
    local timestamp=$(date +%s)

    MENU_HISTORY+=("$timestamp|$menu_name|$choice")
}

# Get menu history
# Usage: menu_get_history
menu_get_history() {
    printf '%s\n' "${MENU_HISTORY[@]}"
}

# Clear menu history
# Usage: menu_clear_history
menu_clear_history() {
    MENU_HISTORY=()
}

# Get last menu choice
# Usage: last_choice=$(menu_get_last_choice)
menu_get_last_choice() {
    local hist_len=${#MENU_HISTORY[@]}
    if [ "$hist_len" -gt 0 ]; then
        local last="${MENU_HISTORY[$((hist_len - 1))]}"
        echo "${last##*|}"
    fi
}

################################################################################
# NUMERIC INPUT VALIDATION
################################################################################

# Robust numeric validation
# Usage: is_numeric 123
is_numeric() {
    local input="$1"
    [[ "$input" =~ ^[0-9]+$ ]]
}

# Get integer value with bounds checking
# Usage: get_int_choice "$MENU_CHOICE" 0 10
# Returns: 0 if valid, 1 if invalid
get_int_choice() {
    local choice="$1"
    local min="$2"
    local max="$3"

    # Must be numeric
    if ! is_numeric "$choice"; then
        return 1
    fi

    # Check bounds
    if [ "$choice" -ge "$min" ] && [ "$choice" -le "$max" ]; then
        return 0
    fi

    return 1
}

# Sanitize input (remove special characters)
# Usage: sanitized=$(sanitize_input "$user_input")
sanitize_input() {
    local input="$1"
    # Remove all non-alphanumeric characters
    echo "$input" | tr -cd '[:alnum:]'
}

# Validate menu handler function exists
# Usage: if validate_handler "run_bot_analyzer"; then run_bot_analyzer; fi
validate_handler() {
    local handler="$1"
    declare -f "$handler" > /dev/null
}

################################################################################
# BATCH MODE SUPPORT
################################################################################

# Check if in batch mode (non-interactive execution)
# Usage: if is_batch_mode; then ... fi
is_batch_mode() {
    [ "$BATCH_MODE" = "1" ] || [ "$BATCH_MODE" = "true" ]
}

# Set batch mode (skip all menus, use defaults or args)
# Usage: set_batch_mode on/off
set_batch_mode() {
    case "$1" in
        on|true|1) BATCH_MODE=1 ;;
        off|false|0) BATCH_MODE=0 ;;
    esac
    export BATCH_MODE
}

# Menu shortcut for batch mode
# Returns immediately with choice if in batch mode
# Usage: menu_or_batch "1" "Select option" 0 3
menu_or_batch() {
    local default_choice="$1"
    shift

    if is_batch_mode; then
        MENU_CHOICE="$default_choice"
        return 0
    fi

    # Interactive mode
    read_menu_choice "$@"
}

################################################################################
# BREADCRUMB / NAVIGATION PATH
################################################################################

# Display menu breadcrumb/path
# Usage: menu_breadcrumb
menu_breadcrumb() {
    local breadcrumb="Main"
    for item in "${MENU_STACK[@]}"; do
        breadcrumb="$breadcrumb > $item"
    done
    echo "Location: $breadcrumb"
}

# Display menu breadcrumb with option to jump back
# Usage: menu_breadcrumb_interactive
menu_breadcrumb_interactive() {
    local breadcrumb="[Main]"
    local counter=1

    for item in "${MENU_STACK[@]}"; do
        breadcrumb="$breadcrumb [$counter] $item"
        ((counter++))
    done

    echo "$breadcrumb"
}

################################################################################
# MENU VALIDATION
################################################################################

# Validate menu options array is not empty
# Usage: validate_menu_options "option1" "option2" ...
validate_menu_options() {
    if [ $# -eq 0 ]; then
        print_error "Menu has no options defined"
        return 1
    fi
    return 0
}

# Check if option number is disabled
# Usage: is_option_disabled 5 "disabled_options"
is_option_disabled() {
    local option_num="$1"
    local disabled_str="${2:-}"

    # disabled_str format: "3,5,7" (comma-separated numbers)
    if [[ ",$disabled_str," == *",$option_num,"* ]]; then
        return 0
    fi
    return 1
}

################################################################################
# MENU TIMING / TIMEOUT
################################################################################

# Read menu choice with timeout
# Usage: read_menu_choice_timeout 30 "Select option" 0 5
# Will use default (0) if timeout expires
read_menu_choice_timeout() {
    local timeout="$1"
    local prompt="$2"
    local min="$3"
    local max="$4"

    local remaining="$timeout"
    printf "%s (auto-cancel in %d seconds): " "$prompt" "$timeout"

    # Use read with timeout
    if read -t "$timeout" -r MENU_CHOICE; then
        # Got input before timeout
        if validate_menu_choice "$MENU_CHOICE" "$min" "$max"; then
            return 0
        else
            echo ""
            echo "Invalid option."
            return 1
        fi
    else
        # Timeout expired, use default (0 = back/cancel)
        echo ""
        echo "No input received. Returning..."
        MENU_CHOICE=0
        return 0
    fi
}

################################################################################
# PAGINATION FOR LONG MENUS
################################################################################

# Display menu items with pagination
# Usage: menu_paginate 5 "Option 1" "Option 2" "Option 3" ... (show 5 per page)
menu_paginate() {
    local items_per_page="$1"
    shift
    local items=("$@")
    local total=${#items[@]}
    local pages=$((($total + $items_per_page - 1) / $items_per_page))

    if [ "$pages" -le 1 ]; then
        # Just display all
        menu_options "${items[@]}"
        return 0
    fi

    # Multi-page display
    local page=1
    local start=0

    while true; do
        local end=$((start + items_per_page))
        if [ "$end" -gt "$total" ]; then
            end=$total
        fi

        echo ""
        echo "Page $page of $pages:"
        for ((i=start; i<end; i++)); do
            printf "  %d) %s\n" "$((i+1))" "${items[$i]}"
        done

        if [ "$page" -ge "$pages" ]; then
            break
        fi

        echo ""
        printf "Press Enter for next page..."
        read -r || break
        ((page++))
        ((start += items_per_page))
    done
}

# Search/filter menu options
# Usage: menu_search "options array" "search term"
menu_search() {
    local search_term="$1"
    shift
    local options=("$@")
    local results=()

    # Convert search term to lowercase for case-insensitive search
    search_term="${search_term,,}"

    for option in "${options[@]}"; do
        if [[ "${option,,}" == *"$search_term"* ]]; then
            results+=("$option")
        fi
    done

    if [ ${#results[@]} -eq 0 ]; then
        echo "No matches found for: $search_term"
        return 1
    fi

    menu_options "${results[@]}"
    return 0
}

################################################################################
# MENU STATE & CACHING
################################################################################

# Save menu state to file for recovery
# Usage: menu_save_state "/tmp/menu_state"
# WARNING: State files can be restored with menu_restore_state, which sources the file.
# Only use with trusted file paths.
menu_save_state() {
    local state_file="$1"

    if [ -z "$state_file" ]; then
        print_error "menu_save_state: file path required"
        return 1
    fi

    {
        echo "# Menu state saved $(date)"
        echo "MENU_STACK=("
        printf '  "%s"\n' "${MENU_STACK[@]}"
        echo ")"
        echo "MENU_HISTORY=("
        printf '  "%s"\n' "${MENU_HISTORY[@]}"
        echo ")"
        echo "MENU_USE_COLORS='$MENU_USE_COLORS'"
        echo "BATCH_MODE='$BATCH_MODE'"
    } > "$state_file"
}

# Restore menu state from file
# Usage: menu_restore_state "/tmp/menu_state"
# SECURITY WARNING: Only restore state files from TRUSTED sources.
# State files are sourced as bash code - never restore from untrusted paths.
menu_restore_state() {
    local state_file="$1"

    if [ -z "$state_file" ]; then
        print_error "menu_restore_state: file path required"
        return 1
    fi

    if [ ! -f "$state_file" ]; then
        print_error "menu_restore_state: file not found: $state_file"
        return 1
    fi

    # Security check: verify file is readable and not a symlink to untrusted location
    if [ -L "$state_file" ]; then
        print_error "menu_restore_state: refusing to restore state from symlink"
        return 1
    fi

    # Source the state file - ONLY from trusted paths!
    # shellcheck disable=SC1090
    source "$state_file" || {
        print_error "menu_restore_state: failed to restore state from $state_file"
        return 1
    }
}

################################################################################
# MENU TEMPLATE GENERATOR
################################################################################

# Generate menu template skeleton
# Usage: menu_template "Security Menu" "Option 1" "Option 2" "Option 3"
# WARNING: This is a code generator. Input should be safe strings only.
menu_template() {
    local title="$1"
    shift
    local options=("$@")

    # Basic validation - check that title is not empty
    if [ -z "$title" ]; then
        print_error "menu_template: title required"
        return 1
    fi

    # Validate that we have options
    if [ $# -eq 0 ]; then
        print_error "menu_template: at least one option required"
        return 1
    fi

    # Escape title for use in bash (replace single quotes)
    title="${title//\'/\'\\\'\'}"

    cat << 'EOF'
#!/bin/bash

# Source required libraries
source "${SCRIPT_DIR}/lib/menu-functions.sh"
source "${SCRIPT_DIR}/lib/common-functions.sh"

# Main menu loop
show_${title,,}_menu() {
    while true; do
        show_menu "$title" "$((${#options[@]}))" "Main Menu" \\
EOF

    for option in "${options[@]}"; do
        echo "            \"$option\" \\"
    done

    cat << 'EOF'

        case "$MENU_CHOICE" in
EOF

    for i in "${!options[@]}"; do
        echo "            $((i+1))) run_option_$((i+1)) ;;"
    done

    cat << 'EOF'
            0) return ;;
            *) menu_invalid_choice ;;
        esac
    done
}

# Option handlers
run_option_1() {
    echo "Option 1 selected"
    menu_press_enter
}

run_option_2() {
    echo "Option 2 selected"
    menu_press_enter
}

# Main execution
show_${title,,}_menu
EOF
}

################################################################################
# MENU DEPTH & NAVIGATION
################################################################################

# Get menu nesting depth (how deep in menu hierarchy)
# Usage: depth=$(menu_depth)
menu_depth() {
    echo "${#MENU_STACK[@]}"
}

# Display menu depth indicator
# Usage: menu_show_depth
menu_show_depth() {
    local depth=$(menu_depth)
    if [ "$depth" -gt 0 ]; then
        printf "[Level %d] " "$((depth + 1))"
    fi
}

# Display menu hint/help (optional info about available shortcuts)
# Usage: menu_hint "Press 'h' for help, 'q' to quit"
menu_hint() {
    local hint="$1"
    echo ""
    echo "Hint: $hint"
}

# Display keyboard shortcuts available
# Usage: menu_shortcuts "h) Help" "q) Quit" "r) Refresh"
menu_shortcuts() {
    echo ""
    echo "Shortcuts:"
    for shortcut in "$@"; do
        echo "  $shortcut"
    done
}

################################################################################
# KEYBOARD SHORTCUTS & SPECIAL COMMANDS
################################################################################

# Handle special keyboard shortcuts in menu
# Usage: handle_menu_shortcut "$MENU_CHOICE" "show_help_text"
handle_menu_shortcut() {
    local input="$1"
    local help_text="${2:-}"

    case "$input" in
        h|H|help|HELP)
            if [ -n "$help_text" ]; then
                echo "$help_text"
            else
                menu_help
            fi
            menu_press_enter
            return 1  # Indicate shortcut was handled, redraw menu
            ;;
        q|Q|quit|QUIT|exit|EXIT)
            return 2  # Indicate user wants to exit
            ;;
        *)
            return 0  # Not a shortcut, continue normally
            ;;
    esac
}

# Check for keyboard interrupt (Ctrl+C)
# Usage: trap 'menu_interrupt_handler' INT
menu_interrupt_handler() {
    echo ""
    echo "Interrupted by user."
    menu_pop
    return 1
}

################################################################################
# ERROR RECOVERY
################################################################################

# Wrap menu handler with error recovery
# Usage: menu_safe_execute "handler_function" "arg1" "arg2"
menu_safe_execute() {
    local handler="$1"
    shift

    if ! validate_handler "$handler"; then
        print_error "Handler not found: $handler"
        return 1
    fi

    # Try to execute handler with error recovery
    if "$handler" "$@"; then
        return 0
    else
        local exit_code=$?
        print_error "Handler failed with code: $exit_code"
        return "$exit_code"
    fi
}

# Menu execution with timeout and recovery
# Usage: menu_execute_with_timeout 300 "handler_function"
menu_execute_with_timeout() {
    local timeout="$1"
    local handler="$2"
    shift 2
    local args=("$@")

    if ! timeout "$timeout" "$handler" "${args[@]}" 2>/dev/null; then
        local exit_code=$?
        if [ "$exit_code" = "124" ]; then
            print_error "Operation timed out after ${timeout}s"
        else
            print_error "Operation failed with code: $exit_code"
        fi
        return "$exit_code"
    fi
}

################################################################################
# HELP/DOCUMENTATION
################################################################################

# Display menu functions help
menu_help() {
    cat << 'EOF'
Menu Functions Library - Available Functions

=== DISPLAY FUNCTIONS ===
  menu_header "Title"              - Display menu header with separator
  menu_option 1 "Label" "Desc"     - Display numbered option
  menu_option_wrapped 1 "L" "Desc" - Display option with text wrapping
  menu_option_status 1 "L" "stat"  - Option with status [enabled]
  menu_option_default 1 "L" true   - Option marked as [DEFAULT]
  menu_option_disabled 1 "L"       - Show disabled option
  menu_options "Opt1" "Opt2"       - Auto-number multiple options
  menu_options_with_default "1" "O1" "O2" - Auto-number with default
  menu_divider                     - Display separator line
  menu_back "Main Menu"            - Display back option
  menu_exit                        - Display exit option (main menu)
  menu_section "Group"             - Display section header
  menu_group "Name" 1 "O1" "O2"    - Display grouped options
  menu_option_nested 1 "Label"     - Display nested/indented option

=== INPUT FUNCTIONS ===
  read_menu_choice "Prompt" 0 5    - Read and validate user input
  validate_menu_choice 5 0 10      - Check if choice in range
  read_menu_choice_timeout 30 "P" 0 5 - Read with timeout (default 0)
  is_numeric 123                   - Check if input is numeric
  get_int_choice "$CHOICE" 0 10    - Validate integer with bounds

=== ERROR FUNCTIONS ===
  menu_invalid_choice              - Show "invalid option" message
  menu_input_error "msg"           - Show error with context

=== COMPLETE MENU ===
  show_menu "Title" "3" "Back" opt1 opt2 opt3 - All-in-one menu
  menu_loop "Title" "3" "Back" opt1 opt2 opt3  - Menu with loop

=== CONFIRMATION ===
  confirm_action "Delete?"         - Yes/No dialog, returns 0/1

=== HIERARCHY TRACKING ===
  menu_push "Menu Name"            - Push menu onto stack
  menu_pop                         - Pop menu from stack
  menu_current                     - Get current menu name
  menu_parent                      - Get parent menu name
  menu_breadcrumb                  - Show "Main > Menu1 > Menu2"
  menu_breadcrumb_interactive      - Show breadcrumb with numbers
  menu_depth                       - Get nesting depth
  menu_show_depth                  - Display "[Level N]"

=== BATCH MODE ===
  set_batch_mode on/off            - Enable/disable batch mode
  is_batch_mode                    - Check if batch mode active
  menu_or_batch "1" "Prompt" 0 5   - Menu or use batch default

=== MENU HISTORY ===
  menu_log_selection "Menu" 1      - Log user's choice
  menu_get_history                 - Get all logged selections
  menu_get_last_choice             - Get last choice number
  menu_clear_history               - Clear history

=== HINTS & HELP ===
  menu_hint "text"                 - Display hint message
  menu_shortcuts "h) Help" "q) Quit" - Display shortcuts
  validate_menu_options "O1" "O2"  - Check menu has options
  is_option_disabled 5 "3,5,7"     - Check if option disabled

=== UTILITIES ===
  detect_interactive_mode          - Check if TTY available
  menu_press_enter                 - Pause for user
  menu_loading "Scanning..."       - Show loading indicator

=== BASIC EXAMPLE ===
  source lib/menu-functions.sh

  while true; do
      show_menu "Security Menu" "3" "Main Menu" \
          "Bot Analyzer" \
          "Malware Scanner" \
          "IP Reputation Manager"

      case "$MENU_CHOICE" in
          1) run_bot_analyzer ;;
          2) run_malware_scanner ;;
          3) run_ip_reputation ;;
          0) return ;;
          *) menu_invalid_choice ;;
      esac
  done

=== ADVANCED EXAMPLE ===
  source lib/menu-functions.sh

  menu_push "Security Menu"

  while true; do
      menu_show_depth
      menu_header "Threat Analysis"
      menu_option 1 "Bot Analyzer"
      menu_option_status 2 "Malware Scanner" "enabled"
      menu_option_disabled 3 "Advanced" "(admin only)"
      echo ""
      menu_back "$(menu_parent)"
      menu_divider
      menu_hint "Type number and press Enter"

      read_menu_choice "Select" 0 3

      case "$MENU_CHOICE" in
          1) menu_log_selection "Threat" 1; run_bot_analyzer ;;
          2) menu_log_selection "Threat" 2; run_malware_scanner ;;
          0) menu_pop; return ;;
          *) menu_invalid_choice ;;
      esac
  done
EOF
}

################################################################################
# COLOR SUPPORT (OPTIONAL - DISABLED BY DEFAULT FOR COMPATIBILITY)
################################################################################

# Enable colors if terminal supports it (optional)
# Usage: enable_menu_colors
enable_menu_colors() {
    MENU_USE_COLORS=1
    export MENU_USE_COLORS
}

# Disable colors (default)
# Usage: disable_menu_colors
disable_menu_colors() {
    MENU_USE_COLORS=0
    export MENU_USE_COLORS
}

# Conditional color output (if enabled)
# Usage: menu_color_text "31" "ERROR"  (31 = red)
menu_color_text() {
    local color_code="$1"
    local text="$2"

    if [ "${MENU_USE_COLORS:-0}" = "1" ]; then
        printf "\033[%sm%s\033[0m\n" "$color_code" "$text"
    else
        echo "$text"
    fi
}

################################################################################
# ERROR MESSAGE FALLBACKS
################################################################################

# Fallback if common-functions.sh not sourced
if ! declare -F print_error > /dev/null; then
    print_error() {
        echo "[ERROR] $1" >&2
    }
fi

if ! declare -F print_warning > /dev/null; then
    print_warning() {
        echo "[WARNING] $1"
    }
fi

if ! declare -F show_banner > /dev/null; then
    show_banner() {
        echo ""
        echo "=================================================="
    }
fi

if ! declare -F press_enter > /dev/null; then
    press_enter() {
        echo ""
        printf "Press Enter to continue..."
        read -r || true
    }
fi

################################################################################
# INITIALIZATION
################################################################################

# Declare global menu state variables
declare -g MENU_STACK=()
declare -g MENU_HISTORY=()
declare -g INTERACTIVE_MODE=0

# Detect interactive mode on library load (ignore return code)
# This sets INTERACTIVE_MODE=1 if interactive, 0 if non-interactive
detect_interactive_mode || true

# Export all functions for sourcing
export -f menu_header menu_option menu_option_wrapped menu_divider menu_back menu_exit
export -f read_menu_choice validate_menu_choice read_menu_choice_timeout
export -f menu_invalid_choice menu_input_error
export -f show_menu detect_interactive_mode
export -f confirm_action menu_option_nested menu_section menu_option_status
export -f menu_option_disabled menu_option_default menu_options menu_options_with_default menu_group
export -f clear_and_banner menu_press_enter menu_loading
export -f menu_push menu_pop menu_current menu_parent menu_breadcrumb menu_breadcrumb_interactive
export -f menu_help menu_loop show_invalid_choice
export -f print_error print_warning show_banner press_enter
export -f is_batch_mode set_batch_mode menu_or_batch
export -f validate_menu_options is_option_disabled
export -f menu_log_selection menu_get_history menu_clear_history menu_get_last_choice
export -f is_numeric get_int_choice
export -f menu_depth menu_show_depth menu_hint menu_shortcuts
export -f enable_menu_colors disable_menu_colors menu_color_text
export -f menu_save_state menu_restore_state menu_template
export -f sanitize_input validate_handler
export -f menu_paginate menu_search
export -f handle_menu_shortcut menu_interrupt_handler
export -f menu_safe_execute menu_execute_with_timeout

