#!/bin/bash
#
# npx安装脚本 - 安装nvm、Node.js和npx
#

# 设置错误处理
set -e
trap 'echo "错误：安装失败，请查看上面的错误信息"; exit 1' ERR

# 彩色输出函数
info() { printf "\033[0;36m%s\033[0m\n" "$1"; }
success() { printf "\033[0;32m%s\033[0m\n" "$1"; }
warning() { printf "\033[0;33m%s\033[0m\n" "$1"; }
error() { printf "\033[0;31m%s\033[0m\n" "$1"; }

# 初始化变量
ENV_UPDATED=false
MAIN_SHELL_FILE=""

info "正在启动npx安装..."

# 1. 首先检查是否已有npx
if command -v npx &> /dev/null; then
    success "npx已安装，版本：$(npx -v)"
    exit 0
fi

# 2. 检查是否已安装Node.js
if command -v node &> /dev/null; then
    success "Node.js已安装，版本：$(node -v)"
    
    # 检查npm版本是否支持npx (npm 5.2.0+)
    info "正在检查Node.js版本是否支持npx..."
    NPM_VERSION=$(npm -v)
    NPM_MAJOR=$(echo $NPM_VERSION | cut -d. -f1)
    NPM_MINOR=$(echo $NPM_VERSION | cut -d. -f2)
    
    # 判断npm版本是否原生支持npx
    NPX_SUPPORTED=false
    if [ "$NPM_MAJOR" -ge 6 ]; then
        NPX_SUPPORTED=true
    elif [ "$NPM_MAJOR" -eq 5 ] && [ "$NPM_MINOR" -ge 2 ]; then
        NPX_SUPPORTED=true
    fi
    
    if [ "$NPX_SUPPORTED" = true ]; then
        warning "npm版本应该支持npx，但未找到npx命令"
        info "尝试通过npm安装npx..."
        npm install -g npx
        if command -v npx &> /dev/null; then
            success "npx安装成功，版本：$(npx -v)"
            exit 0
        fi
        warning "无法通过现有Node.js安装npx，将使用nvm安装新版本Node.js"
    else
        warning "当前npm版本($NPM_VERSION)不支持npx，需要npm 5.2.0+"
        info "将使用nvm安装支持npx的Node.js版本"
    fi
else
    info "未检测到Node.js，将安装Node.js以获取npx"
fi

# 3. 检查并安装nvm
if ! command -v nvm &> /dev/null; then
    info "正在安装nvm..."
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh | bash
    export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/.nvm")"
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    success "nvm安装完成"
else
    success "nvm已安装"
    export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/.nvm")"
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
fi

# 确保nvm环境变量已添加到shell配置文件
info "正在检查nvm环境变量配置..."

# 确定shell配置文件
SHELL_FILES=()
if [ -n "$SHELL" ]; then
    case "$SHELL" in
        */zsh)
            SHELL_FILES=("$HOME/.zshrc")
            [ -f "$HOME/.zprofile" ] && SHELL_FILES+=("$HOME/.zprofile")
            ;;
        */bash)
            SHELL_FILES=("$HOME/.bashrc")
            [ -f "$HOME/.bash_profile" ] && SHELL_FILES+=("$HOME/.bash_profile")
            ;;
        *)
            SHELL_FILES=("$HOME/.profile")
            ;;
    esac
else
    # 如果$SHELL未定义，尝试检测常见的配置文件
    [ -f "$HOME/.bashrc" ] && SHELL_FILES+=("$HOME/.bashrc")
    [ -f "$HOME/.zshrc" ] && SHELL_FILES+=("$HOME/.zshrc")
    [ -f "$HOME/.profile" ] && SHELL_FILES+=("$HOME/.profile")
fi

# 如果没有找到任何配置文件，创建一个默认的
if [ ${#SHELL_FILES[@]} -eq 0 ]; then
    SHELL_FILES=("$HOME/.profile")
    touch "$HOME/.profile"
fi

# 检查nvm配置
NVM_CONFIG_FOUND=false
NVM_CONFIG_CORRECT=false
for SHELL_FILE in "${SHELL_FILES[@]}"; do
    if [ -f "$SHELL_FILE" ] && grep -q "NVM_DIR" "$SHELL_FILE"; then
        NVM_CONFIG_FOUND=true
        # 检查nvm初始化代码是否正确
        if grep -q "\[ -s \"\$NVM_DIR/nvm.sh\" \]" "$SHELL_FILE"; then
            NVM_CONFIG_CORRECT=true
            info "nvm配置已正确存在于$SHELL_FILE中"
        else
            warning "在$SHELL_FILE中找到nvm配置，但可能不正确"
            # 尝试修复nvm配置
            if grep -q "s \"\$NVM_DIR/nvm.sh\" \]" "$SHELL_FILE"; then
                info "正在修复$SHELL_FILE中的nvm配置..."
                # 创建备份
                cp "$SHELL_FILE" "${SHELL_FILE}.bak.$(date +%Y%m%d%H%M%S)"
                info "已创建备份: ${SHELL_FILE}.bak.$(date +%Y%m%d%H%M%S)"
                # 修复配置
                sed -i '' 's/s "\$NVM_DIR\/nvm.sh" \]/\[ -s "\$NVM_DIR\/nvm.sh" \]/g' "$SHELL_FILE"
                NVM_CONFIG_CORRECT=true
                ENV_UPDATED=true
                info "已修复$SHELL_FILE中的nvm配置"
            fi
        fi
    fi
done

if [ "$NVM_CONFIG_FOUND" = false ] || [ "$NVM_CONFIG_CORRECT" = false ]; then
    if [ "$NVM_CONFIG_FOUND" = false ]; then
        warning "未找到nvm配置，正在添加..."
    else
        warning "nvm配置不正确，正在修复..."
    fi
    # 选择主要的shell配置文件
    if [ -n "$SHELL" ] && [[ "$SHELL" == */zsh ]]; then
        MAIN_SHELL_FILE="$HOME/.zshrc"
    elif [ -n "$SHELL" ] && [[ "$SHELL" == */bash ]]; then
        MAIN_SHELL_FILE="$HOME/.bashrc"
    else
        MAIN_SHELL_FILE="$HOME/.profile"
    fi
    
    # 创建备份
    if [ -f "$MAIN_SHELL_FILE" ]; then
        cp "$MAIN_SHELL_FILE" "${MAIN_SHELL_FILE}.bak.$(date +%Y%m%d%H%M%S)"
        info "已创建备份: ${MAIN_SHELL_FILE}.bak.$(date +%Y%m%d%H%M%S)"
    fi
    
    # 添加nvm配置
    printf "\n# 由npx安装脚本添加 - %s\n" "$(date)" >> "$MAIN_SHELL_FILE"
    printf 'export NVM_DIR="$HOME/.nvm"\n' >> "$MAIN_SHELL_FILE"
    printf '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # 加载nvm\n' >> "$MAIN_SHELL_FILE"
    printf '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # 加载nvm bash_completion\n' >> "$MAIN_SHELL_FILE"
    info "已将nvm配置添加到$MAIN_SHELL_FILE"
    ENV_UPDATED=true
fi

# 4. 使用nvm安装Node.js (仅当需要时)
info "正在安装支持npx的Node.js版本..."
nvm install --lts
success "Node.js安装完成，版本：$(node -v)"

# 5. 验证npx是否可用
if ! command -v npx &> /dev/null; then
    error "npx未找到，请确保Node.js安装正确"
    exit 1
fi

# 显示安装信息
success "安装成功！"
info "Node.js版本：$(node -v)"
info "npm版本：$(npm -v)"
info "npx版本：$(npx -v)"

# 自动使环境变量生效
if [ "$NVM_CONFIG_FOUND" = false ] || [ "$ENV_UPDATED" = true ]; then
    if [ -n "$MAIN_SHELL_FILE" ] && [ -f "$MAIN_SHELL_FILE" ]; then
        source "$MAIN_SHELL_FILE"
    else
        for SHELL_FILE in "${SHELL_FILES[@]}"; do
            if [ -f "$SHELL_FILE" ] && grep -q "NVM_DIR" "$SHELL_FILE"; then
                source "$SHELL_FILE"
                break
            fi
        done
    fi
fi
