#!/bin/bash

# Universal Nushell + Plugins Bootstrap Installer
# POSIX compliant shell script that installs Nushell and plugins without any prerequisites
#
# This script:
# - Detects platform (Linux/macOS, x86_64/arm64)
# - Downloads or builds Nushell + plugins
# - Installs to user location (~/.local/bin) or system (/usr/local/bin)
# - Updates PATH in shell configuration files
# - Creates initial Nushell configuration
# - Registers all plugins automatically
# - Verifies installation

set -e  # Exit on error

# Configuration
REPO_URL="https://github.com/jesusperezlorenzo/nushell-plugins"
BINARY_REPO_URL="$REPO_URL/releases/download"
INSTALL_DIR_USER="$HOME/.local/bin"
INSTALL_DIR_SYSTEM="/usr/local/bin"
CONFIG_DIR="$HOME/.config/nushell"
TEMP_DIR="/tmp/nushell-install-$$"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# Logging functions
log_info() {
    printf "${BLUE}ℹ️  %s${NC}\n" "$1"
}

log_success() {
    printf "${GREEN}✅ %s${NC}\n" "$1"
}

log_warn() {
    printf "${YELLOW}⚠️  %s${NC}\n" "$1"
}

log_error() {
    printf "${RED}❌ %s${NC}\n" "$1" >&2
}

log_header() {
    printf "\n${PURPLE}🚀 %s${NC}\n" "$1"
    printf "${PURPLE}%s${NC}\n" "$(printf '=%.0s' $(seq 1 ${#1}))"
}

# Usage information
usage() {
    cat << 'EOF'
Nushell + Plugins Bootstrap Installer

USAGE:
    curl -L install-url/install.sh | sh
    # or
    ./install.sh [OPTIONS]

OPTIONS:
    --system            Install to system directory (/usr/local/bin)
                        ⚠️  Requires sudo if not root: sudo ./install.sh --system

    --user              Install to user directory (~/.local/bin) [default]
                        No sudo required - recommended for most users

    --install-dir PATH  Install to custom directory (PATH must be writable)
                        Bypasses interactive prompts when supplied explicitly
                        Example: --install-dir ~/.local/bin

    --source-path PATH  Install from local archive path (no download needed)
                        Default: ./bin_archives (if --source-path is omitted)
                        Useful for offline installations or pre-built archives
                        Example: --source-path ./distribution/darwin-arm64

    --no-path           Don't modify shell PATH configuration
    --no-config         Don't create initial nushell configuration
    --no-plugins        Install only nushell, skip plugins
    --build-from-source Build from source instead of downloading binaries
    --verify            Verify installation after completion
    --uninstall         Remove nushell and plugins
    --version VERSION   Install specific version (default: latest)
    --help              Show this help message

EXAMPLES:
    # Default installation (user directory, with plugins, no sudo needed)
    curl -L install-url/install.sh | sh

    # Install to custom directory (no prompts, no sudo needed)
    ./install.sh --install-dir ~/.local/bin

    # Install from local archive (default: ./bin_archives)
    ./install.sh --source-path

    # Install from custom local archive path
    ./install.sh --source-path ./distribution/darwin-arm64

    # System installation (requires sudo)
    sudo ./install.sh --system

    # Install without plugins
    ./install.sh --no-plugins

    # Build from source
    ./install.sh --build-from-source

    # Install specific version
    ./install.sh --version latest

TROUBLESHOOTING:
    • Permission denied to /usr/local/bin?
      → Use: --install-dir ~/.local/bin (no sudo needed)
      → Or: sudo ./install.sh --system (for system-wide installation)

    • Not sure which option to use?
      → Default: ./install.sh (installs to ~/.local/bin, no sudo)
      → Safe and recommended for most users
EOF
}

# Platform detection
detect_platform() {
    local os arch

    # Detect OS
    case "$(uname -s)" in
        Linux)  os="linux" ;;
        Darwin) os="darwin" ;;
        CYGWIN*|MINGW*|MSYS*) os="windows" ;;
        *) log_error "Unsupported OS: $(uname -s)"; exit 1 ;;
    esac

    # Detect architecture
    case "$(uname -m)" in
        x86_64|amd64) arch="x86_64" ;;
        aarch64|arm64) arch="arm64" ;;
        armv7l) arch="armv7" ;;
        *) log_error "Unsupported architecture: $(uname -m)"; exit 1 ;;
    esac

    # Special handling for Darwin arm64
    if [ "$os" = "darwin" ] && [ "$arch" = "arm64" ]; then
        arch="arm64"
    fi

    echo "${os}-${arch}"
}

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

# Check dependencies for building from source
check_build_dependencies() {
    local missing=""

    if ! command_exists "git"; then
        missing="$missing git"
    fi

    if ! command_exists "cargo"; then
        missing="$missing cargo"
    fi

    if ! command_exists "rustc"; then
        missing="$missing rust"
    fi

    if [ -n "$missing" ]; then
        log_error "Missing build dependencies:$missing"
        log_info "Please install these tools or use binary installation instead"
        return 1
    fi

    return 0
}

# Download file with progress
download_file() {
    local url="$1"
    local output="$2"
    local desc="${3:-file}"

    log_info "Downloading $desc..."

    if command_exists "curl"; then
        if ! curl -L --fail --progress-bar "$url" -o "$output"; then
            log_error "Failed to download $desc from $url"
            return 1
        fi
    elif command_exists "wget"; then
        if ! wget --progress=bar:force "$url" -O "$output"; then
            log_error "Failed to download $desc from $url"
            return 1
        fi
    else
        log_error "Neither curl nor wget is available"
        return 1
    fi

    log_success "Downloaded $desc"
    return 0
}

# Extract archive
extract_archive() {
    local archive="$1"
    local destination="$2"

    log_info "Extracting archive..."

    case "$archive" in
        *.tar.gz)
            if ! tar -xzf "$archive" -C "$destination"; then
                log_error "Failed to extract $archive"
                return 1
            fi
            ;;
        *.zip)
            if command_exists "unzip"; then
                if ! unzip -q "$archive" -d "$destination"; then
                    log_error "Failed to extract $archive"
                    return 1
                fi
            else
                log_error "unzip command not found"
                return 1
            fi
            ;;
        *)
            log_error "Unsupported archive format: $archive"
            return 1
            ;;
    esac

    log_success "Extracted archive"
    return 0
}

# Get latest release version
get_latest_version() {
    local version=""

    if command_exists "curl"; then
        version=$(curl -s "https://api.github.com/repos/jesusperezlorenzo/nushell-plugins/releases/latest" | \
                 grep '"tag_name":' | \
                 sed -E 's/.*"([^"]+)".*/\1/')
    elif command_exists "wget"; then
        version=$(wget -qO- "https://api.github.com/repos/jesusperezlorenzo/nushell-plugins/releases/latest" | \
                 grep '"tag_name":' | \
                 sed -E 's/.*"([^"]+)".*/\1/')
    fi

    if [ -z "$version" ]; then
        # Fallback to a reasonable default
        version="v0.107.1"
        log_warn "Could not detect latest version, using $version"
    fi

    echo "$version"
}

# Download and install binaries
install_from_binaries() {
    local platform="$1"
    local version="$2"
    local install_dir="$3"
    local include_plugins="$4"

    log_header "Installing from Pre-built Binaries"

    # Create temporary directory
    mkdir -p "$TEMP_DIR"
    cd "$TEMP_DIR"

    # Determine archive name and URL
    local archive_name="nushell-plugins-${platform}-${version}.tar.gz"
    local download_url="${BINARY_REPO_URL}/${version}/${archive_name}"

    # Download archive
    if ! download_file "$download_url" "$archive_name" "Nushell distribution"; then
        log_warn "Binary download failed, trying alternative..."
        # Try without version prefix
        archive_name="nushell-plugins-${platform}.tar.gz"
        download_url="${BINARY_REPO_URL}/latest/${archive_name}"
        if ! download_file "$download_url" "$archive_name" "Nushell distribution (latest)"; then
            log_error "Failed to download binaries"
            return 1
        fi
    fi

    # Extract archive
    if ! extract_archive "$archive_name" "."; then
        return 1
    fi

    # Find extracted directory
    local extract_dir=""
    for dir in */; do
        if [ -d "$dir" ]; then
            extract_dir="$dir"
            break
        fi
    done

    if [ -z "$extract_dir" ]; then
        log_error "No extracted directory found"
        return 1
    fi

    log_info "Installing binaries to $install_dir..."

    # Create install directory
    mkdir -p "$install_dir"

    # Install nushell binary
    local nu_binary="nu"
    if [ "$platform" = "windows-x86_64" ]; then
        nu_binary="nu.exe"
    fi

    # Check for binary - try both root and bin/ subdirectory
    local nu_path="${extract_dir}${nu_binary}"
    if [ ! -f "$nu_path" ]; then
        # Try bin/ subdirectory
        nu_path="${extract_dir}bin/${nu_binary}"
    fi

    if [ -f "$nu_path" ]; then
        cp "$nu_path" "$install_dir/"
        chmod +x "${install_dir}/${nu_binary}"
        log_success "Installed nushell binary"
    else
        log_error "Nushell binary not found in archive (tried root and bin/ directory)"
        return 1
    fi

    # Install plugins if requested
    if [ "$include_plugins" = "true" ]; then
        local plugin_count=0

        # Try both root and bin/ subdirectory for plugins
        for plugin_file in "${extract_dir}"nu_plugin_* "${extract_dir}bin/"nu_plugin_*; do
            if [ -f "$plugin_file" ]; then
                local plugin_name=$(basename "$plugin_file")
                cp "$plugin_file" "$install_dir/"
                chmod +x "${install_dir}/${plugin_name}"
                plugin_count=$((plugin_count + 1))
            fi
        done

        if [ $plugin_count -gt 0 ]; then
            log_success "Installed $plugin_count plugins"
        else
            log_warn "No plugins found in archive"
        fi
    fi

    # Copy configuration files if they exist
    if [ -d "${extract_dir}config/" ]; then
        mkdir -p "$CONFIG_DIR"
        cp -r "${extract_dir}config/"* "$CONFIG_DIR/"
        log_success "Installed configuration files"
    fi

    return 0
}

# Build and install from source
install_from_source() {
    local install_dir="$1"
    local include_plugins="$2"

    log_header "Building from Source"

    # Check dependencies
    if ! check_build_dependencies; then
        return 1
    fi

    # Create temporary directory
    mkdir -p "$TEMP_DIR"
    cd "$TEMP_DIR"

    # Clone repository
    log_info "Cloning repository..."
    if ! git clone --recursive "https://github.com/jesusperezlorenzo/nushell-plugins" nushell-plugins; then
        log_error "Failed to clone repository"
        return 1
    fi

    cd nushell-plugins

    # Build nushell
    log_info "Building nushell..."
    if command_exists "just"; then
        if ! just build-nushell; then
            log_error "Failed to build nushell with just"
            return 1
        fi
    else
        # Fallback to manual build
        cd nushell
        if ! cargo build --release --features "plugin,network,sqlite,trash-support,rustls-tls"; then
            log_error "Failed to build nushell"
            return 1
        fi
        cd ..
    fi

    # Build plugins if requested
    if [ "$include_plugins" = "true" ]; then
        log_info "Building plugins..."
        if command_exists "just"; then
            if ! just build; then
                log_warn "Failed to build some plugins"
            fi
        else
            # Build plugins manually
            for plugin_dir in nu_plugin_*; do
                if [ -d "$plugin_dir" ] && [ "$plugin_dir" != "nushell" ]; then
                    log_info "Building $plugin_dir..."
                    cd "$plugin_dir"
                    if cargo build --release; then
                        log_success "Built $plugin_dir"
                    else
                        log_warn "Failed to build $plugin_dir"
                    fi
                    cd ..
                fi
            done
        fi
    fi

    # Install binaries
    log_info "Installing binaries to $install_dir..."
    mkdir -p "$install_dir"

    # Install nushell
    local nu_binary="nushell/target/release/nu"
    if [ -f "$nu_binary" ]; then
        cp "$nu_binary" "$install_dir/"
        chmod +x "${install_dir}/nu"
        log_success "Installed nushell binary"
    else
        log_error "Nushell binary not found"
        return 1
    fi

    # Install plugins
    if [ "$include_plugins" = "true" ]; then
        local plugin_count=0
        for plugin_dir in nu_plugin_*; do
            if [ -d "$plugin_dir" ] && [ "$plugin_dir" != "nushell" ]; then
                local plugin_binary="${plugin_dir}/target/release/${plugin_dir}"
                if [ -f "$plugin_binary" ]; then
                    cp "$plugin_binary" "$install_dir/"
                    chmod +x "${install_dir}/${plugin_dir}"
                    plugin_count=$((plugin_count + 1))
                fi
            fi
        done

        if [ $plugin_count -gt 0 ]; then
            log_success "Installed $plugin_count plugins"
        else
            log_warn "No plugins were built successfully"
        fi
    fi

    return 0
}

# Install from local source (directory or extracted archive)
install_from_local() {
    local source_dir="$1"
    local install_dir="$2"
    local include_plugins="$3"

    log_header "Installing from Local Source"

    # Ensure install directory exists
    mkdir -p "$install_dir"

    # Look for nushell binary
    local nu_binary=""
    if [ -f "$source_dir/nu" ]; then
        nu_binary="$source_dir/nu"
    elif [ -f "$source_dir/bin/nu" ]; then
        nu_binary="$source_dir/bin/nu"
    fi

    if [ -z "$nu_binary" ]; then
        log_error "Nushell binary not found in: $source_dir"
        return 1
    fi

    # Copy nushell binary (preserve attributes for macOS compatibility)
    log_info "Copying nushell binary..."
    cp -p "$nu_binary" "$install_dir/"
    chmod +x "${install_dir}/nu"
    # macOS: Ensure no quarantine attributes that might block execution
    if command -v xattr &> /dev/null; then
        xattr -c "${install_dir}/nu" 2>/dev/null || true
    fi
    log_success "Installed nushell binary"

    # Install plugins if requested
    if [ "$include_plugins" = "true" ]; then
        local plugin_count=0

        # Look for plugin binaries in both root and bin subdirectory
        for plugin_file in "$source_dir"/nu_plugin_* "$source_dir"/bin/nu_plugin_*; do
            if [ -f "$plugin_file" ]; then
                local plugin_name=$(basename "$plugin_file")
                # Skip metadata files (.d files)
                if [[ "$plugin_name" != *.d ]]; then
                    log_info "Copying plugin: $plugin_name"
                    cp -p "$plugin_file" "$install_dir/"
                    chmod +x "${install_dir}/${plugin_name}"
                    # macOS: Clear xattrs that might block execution
                    if command -v xattr &> /dev/null; then
                        xattr -c "${install_dir}/${plugin_name}" 2>/dev/null || true
                    fi
                    plugin_count=$((plugin_count + 1))
                fi
            fi
        done

        if [ $plugin_count -gt 0 ]; then
            log_success "Installed $plugin_count plugins"
        else
            log_info "No plugins found in local source"
        fi
    fi

    return 0
}

# Register plugins with nushell
register_plugins() {
    local install_dir="$1"
    local nu_binary="${install_dir}/nu"

    if [ ! -f "$nu_binary" ]; then
        log_error "Nushell binary not found: $nu_binary"
        return 1
    fi

    log_header "Registering Plugins"

    # Find all plugin binaries
    local plugin_count=0
    local failed_plugins=()
    local incompatible_plugins=()

    for plugin_file in "${install_dir}"/nu_plugin_*; do
        if [ -f "$plugin_file" ] && [ -x "$plugin_file" ]; then
            local plugin_name=$(basename "$plugin_file")
            log_info "Registering $plugin_name..."

            # Capture both stdout and stderr to detect incompatibility
            local output
            output=$("$nu_binary" -c "plugin add '$plugin_file'" 2>&1)
            local exit_code=$?

            if [ $exit_code -eq 0 ]; then
                log_success "Registered $plugin_name"
                plugin_count=$((plugin_count + 1))
            else
                # Check if it's a version incompatibility error
                if echo "$output" | grep -q "is not compatible with version\|is compiled for nushell version"; then
                    log_warn "Skipping $plugin_name: Version mismatch (built for different Nushell version)"
                    incompatible_plugins+=("$plugin_name")
                else
                    log_warn "Failed to register $plugin_name: $(echo "$output" | head -1)"
                    failed_plugins+=("$plugin_name")
                fi
            fi
        fi
    done

    echo ""
    if [ $plugin_count -gt 0 ]; then
        log_success "Successfully registered $plugin_count plugins"
    else
        log_warn "No plugins were registered"
    fi

    # Report incompatible plugins
    if [ ${#incompatible_plugins[@]} -gt 0 ]; then
        log_info ""
        log_warn "Skipped ${#incompatible_plugins[@]} incompatible plugins (version mismatch):"
        for plugin in "${incompatible_plugins[@]}"; do
            log_info "  - $plugin"
        done
        log_info "These plugins were built for a different Nushell version."
        log_info "They can be rebuilt locally if needed or updated in the distribution."
    fi

    # Report failed plugins
    if [ ${#failed_plugins[@]} -gt 0 ]; then
        log_info ""
        log_error "Failed to register ${#failed_plugins[@]} plugins:"
        for plugin in "${failed_plugins[@]}"; do
            log_info "  - $plugin"
        done
    fi

    return 0
}

# Update PATH in shell configuration
update_shell_path() {
    local install_dir="$1"

    log_header "Updating Shell Configuration"

    # List of shell configuration files to update
    local shell_configs=""

    # Detect current shell and add its config file first
    case "$SHELL" in
        */bash) shell_configs="$HOME/.bashrc $HOME/.bash_profile" ;;
        */zsh)  shell_configs="$HOME/.zshrc" ;;
        */fish) shell_configs="$HOME/.config/fish/config.fish" ;;
        */nu)   shell_configs="$HOME/.config/nushell/env.nu" ;;
    esac

    # Add common configuration files
    shell_configs="$shell_configs $HOME/.profile"

    local updated=false
    local path_found=false

    for config_file in $shell_configs; do
        if [ -f "$config_file" ] || [ "$config_file" = "$HOME/.bashrc" ] || [ "$config_file" = "$HOME/.profile" ]; then
            # Check if already in PATH
            if grep -q "$install_dir" "$config_file" 2>/dev/null; then
                log_info "PATH already configured in $(basename "$config_file")"
                path_found=true
                continue
            fi

            # Create config file if it doesn't exist
            if [ ! -f "$config_file" ]; then
                touch "$config_file"
            fi

            # Add PATH update to config file
            case "$config_file" in
                *.fish)
                    echo "fish_add_path $install_dir" >> "$config_file"
                    ;;
                */env.nu)
                    echo "\$env.PATH = (\$env.PATH | split row (char esep) | append \"$install_dir\" | uniq)" >> "$config_file"
                    ;;
                *)
                    echo "" >> "$config_file"
                    echo "# Added by nushell installer" >> "$config_file"
                    echo "export PATH=\"$install_dir:\$PATH\"" >> "$config_file"
                    ;;
            esac

            log_success "Updated $(basename "$config_file")"
            updated=true
            path_found=true
        fi
    done

    if [ "$updated" = "true" ]; then
        log_success "Shell configuration updated"
        log_info "Please restart your terminal or run 'source ~/.bashrc' to apply changes"
    elif [ "$path_found" = "true" ]; then
        log_success "PATH is already configured in your shell configuration files"
        log_info "No changes were needed"
    else
        log_warn "Could not find or update shell configuration files"
        log_info "Please manually add the following to your shell configuration:"
        log_info "export PATH=\"$install_dir:\$PATH\""
    fi

    # Update current session PATH
    export PATH="$install_dir:$PATH"
    log_success "Updated PATH for current session"
}

# Create initial nushell configuration
create_nushell_config() {
    log_header "Creating Nushell Configuration"

    # Create config directory
    mkdir -p "$CONFIG_DIR"

    # Create basic config.nu if it doesn't exist
    local config_file="$CONFIG_DIR/config.nu"
    if [ ! -f "$config_file" ]; then
        cat > "$config_file" << 'EOF'
# Nushell Configuration
# Created by nushell-plugins installer

# Set up basic configuration
$env.config = {
    show_banner: false
    edit_mode: emacs
    shell_integration: true

    table: {
        mode: rounded
        index_mode: always
        show_empty: true
        padding: { left: 1, right: 1 }
    }

    completions: {
        case_sensitive: false
        quick: true
        partial: true
        algorithm: "prefix"
    }

    history: {
        max_size: 10000
        sync_on_enter: true
        file_format: "plaintext"
    }

    filesize: {
        metric: false
        format: "auto"
    }
}

# Load custom commands and aliases
# Add your custom configuration below
EOF
        log_success "Created config.nu"
    else
        log_info "config.nu already exists, skipping"
    fi

    # Create basic env.nu if it doesn't exist
    local env_file="$CONFIG_DIR/env.nu"
    if [ ! -f "$env_file" ]; then
        cat > "$env_file" << 'EOF'
# Nushell Environment Configuration
# Created by nushell-plugins installer

# Environment variables
$env.EDITOR = "nano"
$env.BROWSER = "firefox"

# Nushell specific environment
$env.NU_LIB_DIRS = [
    ($nu.config-path | path dirname | path join "scripts")
]

$env.NU_PLUGIN_DIRS = [
    ($nu.config-path | path dirname | path join "plugins")
]

# Add your custom environment variables below
EOF
        log_success "Created env.nu"
    else
        log_info "env.nu already exists, skipping"
    fi

    # Create scripts directory
    local scripts_dir="$CONFIG_DIR/scripts"
    mkdir -p "$scripts_dir"

    # Create plugins directory
    local plugins_dir="$CONFIG_DIR/plugins"
    mkdir -p "$plugins_dir"
}

# Verify installation
verify_installation() {
    local install_dir="$1"
    local nu_binary="${install_dir}/nu"

    log_header "Verifying Installation"

    # Check if nushell binary exists and is executable
    if [ ! -f "$nu_binary" ]; then
        log_error "Nushell binary not found: $nu_binary"
        return 1
    fi

    if [ ! -x "$nu_binary" ]; then
        log_error "Nushell binary is not executable: $nu_binary"
        return 1
    fi

    # Test nushell version
    log_info "Testing nushell binary..."
    local version_output
    if version_output=$("$nu_binary" --version 2>&1); then
        log_success "Nushell version: $version_output"
    else
        log_error "Failed to run nushell binary"
        log_error "Output: $version_output"
        return 1
    fi

    # Test basic nushell command
    log_info "Testing basic nushell functionality..."
    if "$nu_binary" -c "echo 'Hello from Nushell'" >/dev/null 2>&1; then
        log_success "Basic nushell functionality works"
    else
        log_error "Basic nushell functionality failed"
        return 1
    fi

    # List registered plugins
    log_info "Checking registered plugins..."
    local plugin_output
    if plugin_output=$("$nu_binary" -c "plugin list" 2>&1); then
        local plugin_count=$(echo "$plugin_output" | grep -c "nu_plugin_" || true)
        if [ "$plugin_count" -gt 0 ]; then
            log_success "Found $plugin_count registered plugins"
        else
            log_warn "No plugins are registered"
        fi
    else
        log_warn "Could not check plugin status"
    fi

    # Check PATH
    log_info "Checking PATH configuration..."
    if command -v nu >/dev/null 2>&1; then
        log_success "Nushell is available in PATH"
    else
        log_warn "Nushell is not in PATH. You may need to restart your terminal."
    fi

    log_success "Installation verification complete!"
    return 0
}

# Uninstall function
uninstall_nushell() {
    log_header "Uninstalling Nushell"

    local removed_files=0

    # Remove from user directory
    if [ -d "$INSTALL_DIR_USER" ]; then
        for binary in nu nu_plugin_*; do
            local file_path="$INSTALL_DIR_USER/$binary"
            if [ -f "$file_path" ]; then
                rm -f "$file_path"
                log_success "Removed $binary from $INSTALL_DIR_USER"
                removed_files=$((removed_files + 1))
            fi
        done
    fi

    # Remove from system directory (if accessible)
    if [ -w "$INSTALL_DIR_SYSTEM" ] 2>/dev/null; then
        for binary in nu nu_plugin_*; do
            local file_path="$INSTALL_DIR_SYSTEM/$binary"
            if [ -f "$file_path" ]; then
                rm -f "$file_path"
                log_success "Removed $binary from $INSTALL_DIR_SYSTEM"
                removed_files=$((removed_files + 1))
            fi
        done
    fi

    # Option to remove configuration
    printf "Remove nushell configuration directory ($CONFIG_DIR)? [y/N]: "
    read -r response
    case "$response" in
        [yY]|[yY][eE][sS])
            if [ -d "$CONFIG_DIR" ]; then
                rm -rf "$CONFIG_DIR"
                log_success "Removed configuration directory"
            fi
            ;;
        *)
            log_info "Configuration directory preserved"
            ;;
    esac

    if [ $removed_files -gt 0 ]; then
        log_success "Uninstallation complete ($removed_files files removed)"
        log_warn "You may need to manually remove PATH entries from your shell configuration"
    else
        log_warn "No nushell files found to remove"
    fi
}

# Main installation function
main() {
    local install_mode="user"
    local custom_install_dir=""
    local source_path=""
    local modify_path="true"
    local create_config="true"
    local include_plugins="true"
    local build_from_source="false"
    local verify_install="false"
    local do_uninstall="false"
    local version=""

    # Parse command line arguments
    while [ $# -gt 0 ]; do
        case "$1" in
            --system)
                install_mode="system"
                shift
                ;;
            --user)
                install_mode="user"
                shift
                ;;
            --install-dir)
                custom_install_dir="$2"
                shift 2
                ;;
            --source-path)
                # If path is provided, use it; otherwise default to ./bin_archives
                if [ -n "$2" ] && [ "${2#-}" = "$2" ]; then
                    source_path="$2"
                    shift 2
                else
                    source_path="./bin_archives"
                    shift
                fi
                ;;
            --no-path)
                modify_path="false"
                shift
                ;;
            --no-config)
                create_config="false"
                shift
                ;;
            --no-plugins)
                include_plugins="false"
                shift
                ;;
            --build-from-source)
                build_from_source="true"
                shift
                ;;
            --verify)
                verify_install="true"
                shift
                ;;
            --uninstall)
                do_uninstall="true"
                shift
                ;;
            --version)
                version="$2"
                shift 2
                ;;
            --help)
                usage
                exit 0
                ;;
            *)
                log_error "Unknown option: $1"
                usage
                exit 1
                ;;
        esac
    done

    # Handle uninstall
    if [ "$do_uninstall" = "true" ]; then
        uninstall_nushell
        exit 0
    fi

    # Show header
    log_header "Nushell + Plugins Installer"
    log_info "Universal bootstrap installer for Nushell and plugins"
    log_info ""

    # Detect platform
    local platform
    platform=$(detect_platform)
    log_info "Detected platform: $platform"

    # Determine installation directory
    local install_dir

    # If custom install dir provided, use it directly (bypass all prompts)
    if [ -n "$custom_install_dir" ]; then
        install_dir="$custom_install_dir"
        log_info "Using custom installation directory (via --install-dir): $install_dir"
    elif [ "$install_mode" = "system" ]; then
        install_dir="$INSTALL_DIR_SYSTEM"
        if [ "$(id -u)" != "0" ] && [ ! -w "$(dirname "$install_dir")" ]; then
            log_warn "System installation requires root privileges or write access to $INSTALL_DIR_SYSTEM"
            log_info ""
            log_info "Available options:"

            # Check if existing nu can be found
            if command -v nu >/dev/null 2>&1; then
                local existing_path=$(command -v nu | sed 's|/nu$||')
                log_info "  1) Install to existing nu location: $existing_path"
            fi

            log_info "  2) Install to user directory: $INSTALL_DIR_USER"
            log_info "  3) Run with sudo (requires password)"
            log_info ""

            # Interactive prompt
            if [ -t 0 ]; then
                read -p "Choose option (1-3) or press Enter for option 2 [default: 2]: " choice
                choice=${choice:-2}

                case "$choice" in
                    1)
                        if command -v nu >/dev/null 2>&1; then
                            install_dir=$(command -v nu | sed 's|/nu$||')
                            log_info "Using existing nu location: $install_dir"
                        else
                            log_error "No existing nu found"
                            exit 1
                        fi
                        ;;
                    2)
                        install_dir="$INSTALL_DIR_USER"
                        log_info "Using user installation directory: $install_dir"
                        ;;
                    3)
                        log_error "Please re-run with sudo: sudo $0 $@"
                        exit 1
                        ;;
                    *)
                        log_error "Invalid option"
                        exit 1
                        ;;
                esac
            else
                # Non-interactive: use user dir as default
                log_info "Non-interactive mode: using user directory"
                install_dir="$INSTALL_DIR_USER"
            fi
        fi
    else
        install_dir="$INSTALL_DIR_USER"
    fi

    log_info "Installing to: $install_dir"

    # Ensure install directory is writable
    mkdir -p "$install_dir" 2>/dev/null || {
        log_error "Cannot write to installation directory: $install_dir"
        log_info "Check permissions or choose a different directory"
        exit 1
    }

    # Handle source-path (local installation)
    if [ -n "$source_path" ]; then
        log_info "Installing from local source: $source_path"

        # Check if source exists
        if [ ! -e "$source_path" ]; then
            log_error "Source path not found: $source_path"
            exit 1
        fi

        # If it's a file (archive), try to extract it
        # BUT: First check if we can use the build directory directly (avoid tar issues)
        if [ -f "$source_path" ]; then
            # Check if build directory is available in current location
            if [ -f "./nushell/target/release/nu" ]; then
                log_info "Found build directory available, using that instead of archive extraction"
                source_path="./nushell/target/release"
                # Treat it as a directory now, skip extraction
            else
                # No build dir, so extract the archive
            log_info "Extracting from archive: $source_path"

            # Create temp directory for extraction
            local extract_dir="$TEMP_DIR/nushell-extract"
            mkdir -p "$extract_dir"

            # Determine file type and extract
            case "$source_path" in
                *.tar.gz|*.tgz)
                    # Extract tar archive
                    # On macOS: use --xattrs to preserve extended attributes (code signatures)
                    # On Linux: standard tar works fine
                    if [ "$(uname -s)" = "Darwin" ]; then
                        tar --xattrs -xzf "$source_path" -C "$extract_dir" || {
                            log_error "Failed to extract tar.gz archive"
                            exit 1
                        }
                    else
                        tar -xzf "$source_path" -C "$extract_dir" || {
                            log_error "Failed to extract tar.gz archive"
                            exit 1
                        }
                    fi
                    ;;
                *.zip)
                    unzip -q "$source_path" -d "$extract_dir" || {
                        log_error "Failed to extract zip archive"
                        exit 1
                    }
                    ;;
                *)
                    log_error "Unsupported archive format: $source_path"
                    exit 1
                    ;;
            esac

            # Find extracted directory and install from it
            # Use -not -path to exclude the extract_dir itself from results
            local extracted=$(find "$extract_dir" -maxdepth 1 -type d -name "nushell-*" -not -path "$extract_dir" | head -1)
            if [ -z "$extracted" ]; then
                # If no nushell-* subdirectory found, check if extract_dir contains bin/nu directly
                extracted="$extract_dir"
            fi

            # Determine where the binaries are located
            local source_for_install=""

            # Check for binaries in multiple locations (in order of preference)
            if [ -f "$extracted/bin/nu" ]; then
                # Archive with subdirectory: nushell-X.Y.Z/bin/nu
                source_for_install="$extracted/bin"
                log_info "Found binaries in $extracted/bin/"
            elif [ -f "$extracted/nu" ]; then
                # Flat archive structure: binaries at root
                source_for_install="$extracted"
                log_info "Found binaries in $extracted/"
            fi

            # If not found yet, search for any nushell-* subdirectory with bin/nu
            if [ -z "$source_for_install" ] && [ -d "$extract_dir" ]; then
                # Exclude extract_dir itself to only find subdirectories
                local nushell_dir=$(find "$extract_dir" -maxdepth 1 -type d -name "nushell-*" -not -path "$extract_dir" ! -empty 2>/dev/null | head -1)
                if [ -n "$nushell_dir" ] && [ -f "$nushell_dir/bin/nu" ]; then
                    source_for_install="$nushell_dir/bin"
                    log_info "Found binaries in $nushell_dir/bin/"
                fi
            fi

            # Last resort: recursive search for any nu binary
            if [ -z "$source_for_install" ]; then
                local nu_binary=$(find "$extract_dir" -type f -name "nu" -executable 2>/dev/null | head -1)
                if [ -n "$nu_binary" ]; then
                    source_for_install=$(dirname "$nu_binary")
                    log_info "Found nu binary at: $source_for_install/nu"
                fi
            fi

            # Validate that we found the binaries
            if [ -z "$source_for_install" ] || [ ! -f "$source_for_install/nu" ]; then
                log_error "No Nushell binary found in extracted archive"
                log_info "Searched locations:"
                log_info "  - $extracted/bin/nu"
                log_info "  - $extracted/nu"
                log_info "  - Any nushell-* subdirectory with bin/nu"
                log_info "  - Recursive search in $extract_dir"
                log_info ""
                log_info "Archive contents:"
                find "$extract_dir" -type f -name "nu" 2>/dev/null | head -10
                exit 1
            fi

            # Install from the correct source directory
            log_info "Installing from extracted archive at: $source_for_install"
            install_from_local "$source_for_install" "$install_dir" "$include_plugins"
            fi
        fi

        # After extraction or build dir use, install from source_path if it's a directory
        if [ -d "$source_path" ]; then
            # It's a directory (either build dir or extracted), install directly from it
            log_info "Installing from local directory: $source_path"
            install_from_local "$source_path" "$install_dir" "$include_plugins"
        fi

        # Skip the rest of installation
        local build_from_source="skip_download"
    fi

    # Get version if not specified and not using local source
    if [ -z "$version" ] && [ "$build_from_source" != "skip_download" ]; then
        version=$(get_latest_version)
    fi

    if [ "$build_from_source" != "skip_download" ]; then
        log_info "Version: $version"
    fi

    # Cleanup function
    cleanup() {
        if [ -d "$TEMP_DIR" ]; then
            rm -rf "$TEMP_DIR"
        fi
    }
    trap cleanup EXIT

    # Install based on method (skip if already did local source installation)
    if [ "$build_from_source" = "skip_download" ]; then
        log_info "Local source installation completed"
    elif [ "$build_from_source" = "true" ]; then
        if ! install_from_source "$install_dir" "$include_plugins"; then
            log_error "Source installation failed"
            exit 1
        fi
    else
        if ! install_from_binaries "$platform" "$version" "$install_dir" "$include_plugins"; then
            log_error "Binary installation failed"
            exit 1
        fi
    fi

    # Register plugins
    if [ "$include_plugins" = "true" ]; then
        register_plugins "$install_dir"
    fi

    # Update PATH
    if [ "$modify_path" = "true" ]; then
        update_shell_path "$install_dir"
    fi

    # Create configuration
    if [ "$create_config" = "true" ]; then
        create_nushell_config
    fi

    # Verify installation
    if [ "$verify_install" = "true" ]; then
        if ! verify_installation "$install_dir"; then
            log_error "Installation verification failed"
            exit 1
        fi
    fi

    # Final success message
    log_header "Installation Complete!"
    log_success "Nushell has been successfully installed to $install_dir"

    if [ "$include_plugins" = "true" ]; then
        log_success "Plugins have been registered with Nushell"
    fi

    if [ "$modify_path" = "true" ]; then
        log_info "To use Nushell, restart your terminal or run:"
        log_info "  source ~/.bashrc  # or your shell's config file"
    fi

    log_info ""
    log_info "Try running: nu --version"
    log_info "Or start Nushell with: nu"

    if [ "$include_plugins" = "true" ]; then
        log_info "Check plugins with: nu -c 'plugin list'"
    fi

    log_info ""
    log_info "For more information, visit: https://nushell.sh"
    log_info ""
    log_success "Happy shell scripting! 🚀"
}

# Run main function with all arguments
main "$@"
