#!/usr/bin/env bash
# Shared utilities for Unix scripts
# Provides: colors, progress indicators, interactive detection

# Detect if running in interactive shell
is_interactive() {
    [[ -t 0 && -t 1 ]]
}

# Color definitions (only used in interactive mode)
if is_interactive && [[ "${NO_COLOR:-}" != "1" ]]; then
    COLOR_RESET='\033[0m'
    COLOR_RED='\033[0;31m'
    COLOR_GREEN='\033[0;32m'
    COLOR_YELLOW='\033[0;33m'
    COLOR_BLUE='\033[0;34m'
    COLOR_MAGENTA='\033[0;35m'
    COLOR_CYAN='\033[0;36m'
    COLOR_GRAY='\033[0;90m'
    COLOR_BOLD='\033[1m'
else
    COLOR_RESET=''
    COLOR_RED=''
    COLOR_GREEN=''
    COLOR_YELLOW=''
    COLOR_BLUE=''
    COLOR_MAGENTA=''
    COLOR_CYAN=''
    COLOR_GRAY=''
    COLOR_BOLD=''
fi

# Logging functions
log_info() {
    echo -e "${COLOR_BLUE}${1}${COLOR_RESET}"
}

log_success() {
    echo -e "${COLOR_GREEN}${1}${COLOR_RESET}"
}

log_warning() {
    echo -e "${COLOR_YELLOW}${1}${COLOR_RESET}"
}

log_error() {
    echo -e "${COLOR_RED}${1}${COLOR_RESET}" >&2
}

log_step() {
    echo -e "${COLOR_MAGENTA}${1}${COLOR_RESET}"
}

log_result() {
    echo -e "${COLOR_CYAN}${1}${COLOR_RESET}"
}

# Spinner animation (only for interactive shells)
SPINNER_FRAMES=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
SPINNER_PID=""

start_spinner() {
    local message="${1:-Processing...}"

    if ! is_interactive; then
        echo "$message"
        return
    fi

    {
        local i=0
        while true; do
            printf "\r${COLOR_CYAN}${SPINNER_FRAMES[$i]}${COLOR_RESET} %s" "$message"
            i=$(( (i + 1) % ${#SPINNER_FRAMES[@]} ))
            sleep 0.1
        done
    } &
    SPINNER_PID=$!

    # Ensure spinner is cleaned up on script exit
    trap "stop_spinner" EXIT INT TERM
}

stop_spinner() {
    if [[ -n "$SPINNER_PID" ]] && kill -0 "$SPINNER_PID" 2>/dev/null; then
        kill "$SPINNER_PID" 2>/dev/null
        wait "$SPINNER_PID" 2>/dev/null
        SPINNER_PID=""
    fi

    if is_interactive; then
        printf "\r\033[K"  # Clear the spinner line
    fi
}

update_spinner_message() {
    local message="${1:-Processing...}"

    if ! is_interactive; then
        echo "$message"
        return
    fi

    if [[ -n "$SPINNER_PID" ]] && kill -0 "$SPINNER_PID" 2>/dev/null; then
        stop_spinner
        start_spinner "$message"
    fi
}

# Execute command with progress indicator
run_with_progress() {
    local message="$1"
    shift
    local cmd=("$@")

    if is_interactive; then
        start_spinner "$message"
        local output
        local exit_code

        # Capture output and exit code
        output=$("${cmd[@]}" 2>&1)
        exit_code=$?

        stop_spinner

        if [[ $exit_code -eq 0 ]]; then
            log_success "✓ $message - Done!"
        else
            log_error "✗ $message - Failed!"
            echo "$output"
        fi

        return $exit_code
    else
        # Non-interactive: just show message and run
        echo "→ $message"
        "${cmd[@]}"
        local exit_code=$?

        if [[ $exit_code -eq 0 ]]; then
            echo "✓ $message - Done!"
        else
            echo "✗ $message - Failed!"
        fi

        return $exit_code
    fi
}

# Check if command exists
command_exists() {
    command -v "$1" >/dev/null 2>&1
}

# Validate system requirements
check_system_requirements() {
    local min_cpu="${1:-4}"
    local min_ram_gb="${2:-6}"
    local min_disk_gb="${3:-20}"

    log_step "Checking system requirements..."

    # Check CPU cores
    local cpu_count
    cpu_count=$(getconf _NPROCESSORS_ONLN)

    if [[ "$cpu_count" -lt "$min_cpu" ]]; then
        log_error "Insufficient CPU cores: $cpu_count (minimum: $min_cpu)"
        return 1
    fi

    # Check RAM
    local total_mem_gb
    if [[ -f /proc/meminfo ]]; then
        local mem_kb
        mem_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
        total_mem_gb=$(awk "BEGIN {printf \"%.2f\", $mem_kb/1024/1024}")
    else
        local total_mem_bytes
        total_mem_bytes=$(sysctl -n hw.memsize 2>/dev/null || echo "0")
        total_mem_gb=$(awk "BEGIN {printf \"%.2f\", $total_mem_bytes/1024/1024/1024}")
    fi

    if ! awk "BEGIN {exit !($total_mem_gb >= $min_ram_gb)}"; then
        log_error "Insufficient RAM: ${total_mem_gb}GB (minimum: ${min_ram_gb}GB)"
        return 1
    fi

    # Check disk space
    local avail_kb free_gb
    avail_kb=$(df -k . | tail -1 | awk '{print $4}')
    free_gb=$(awk "BEGIN {printf \"%.2f\", $avail_kb/1024/1024}")

    if ! awk "BEGIN {exit !($free_gb >= $min_disk_gb)}"; then
        log_error "Insufficient disk space: ${free_gb}GB (minimum: ${min_disk_gb}GB)"
        return 1
    fi

    log_success "System requirements met: CPU cores=$cpu_count, RAM=${total_mem_gb}GB, FreeDisk=${free_gb}GB"
    return 0
}

# Confirm action (returns 0 for yes, 1 for no)
confirm() {
    local prompt="${1:-Are you sure?}"
    local response

    if ! is_interactive; then
        # In non-interactive mode, assume yes
        return 0
    fi

    read -r -p "$prompt [y/N]: " response
    case "$response" in
        [yY][eE][sS]|[yY])
            return 0
            ;;
        *)
            return 1
            ;;
    esac
}
