#!/bin/bash
# ============================================================
# 一键安装开发环境及四个 AI CLI 工具 (Linux 版)
# - Node.js (配置 npm 国内镜像)
# - Claude Code / Codex CLI / Gemini CLI / Droid CLI / OpenClaw
# - Git (可选)
#
# 支持的 Linux 发行版:
# - Ubuntu / Debian
# - CentOS / RHEL / Fedora
# - Arch Linux
# ============================================================

set -e  # 遇到错误立即退出
set -o pipefail  # 管道命令任何一步失败则整体失败

# ============================================================
# 全局变量定义
# ============================================================

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'  # No Color

# 国内镜像 URL
NPM_REGISTRY="https://registry.npmmirror.com"
# Node.js 使用淘宝镜像预编译包（速度快，适用所有发行版）
NODE_VERSION="24.13.1"
NODE_MIRROR_BASE="https://registry.npmmirror.com/-/binary/node/v${NODE_VERSION}"
DROID_INSTALL_URL="https://app.factory.ai/cli/linux"

# 检测到的系统信息
OS_TYPE=""
PKG_MANAGER=""
HOME_DIR="${HOME}"

# ============================================================
# 日志函数
# ============================================================

log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# ============================================================
# 权限检查
# ============================================================

check_root_privileges() {
    log_info "检查权限..."
    if [[ $EUID -ne 0 ]]; then
        log_error "此脚本需要 root 权限运行！"
        log_error "请使用以下命令重新运行："
        log_error "  sudo bash $0"
        exit 1
    fi
    log_success "权限检查通过。"
}

# ============================================================
# 系统检测
# ============================================================

detect_os() {
    log_info "检测操作系统..."

    if [[ -f /etc/os-release ]]; then
        . /etc/os-release
        OS_TYPE="$ID"
        log_success "检测到系统: $NAME ($VERSION)"
    elif [[ -f /etc/lsb-release ]]; then
        . /etc/lsb-release
        OS_TYPE="$DISTRIB_ID"
        log_success "检测到系统: $DISTRIB_DESCRIPTION"
    else
        log_warn "无法检测系统类型，将尝试通用方法。"
        OS_TYPE="unknown"
    fi
}

detect_package_manager() {
    log_info "检测包管理器..."

    if command -v apt-get &> /dev/null; then
        PKG_MANAGER="apt"
        log_success "使用包管理器: apt"
    elif command -v dnf &> /dev/null; then
        PKG_MANAGER="dnf"
        log_success "使用包管理器: dnf"
    elif command -v yum &> /dev/null; then
        PKG_MANAGER="yum"
        log_success "使用包管理器: yum"
    elif command -v pacman &> /dev/null; then
        PKG_MANAGER="pacman"
        log_success "使用包管理器: pacman"
    else
        log_error "未检测到支持的包管理器 (apt/dnf/yum/pacman)。"
        log_error "请手动安装 Node.js 和其他依赖。"
        exit 1
    fi
}

# ============================================================
# 工具检查与安装
# ============================================================

check_required_tools() {
    log_info "检查必要工具..."

    local missing_tools=()

    # 检查下载工具
    if ! command -v curl &> /dev/null && ! command -v wget &> /dev/null; then
        missing_tools+=("curl")
    fi

    # 检查解压工具
    if ! command -v tar &> /dev/null; then
        missing_tools+=("tar")
    fi

    if ! command -v gzip &> /dev/null; then
        missing_tools+=("gzip")
    fi

    # xz 工具（用于解压 tar.xz 格式的 Node.js 包）
    if ! command -v xz &> /dev/null; then
        case "$PKG_MANAGER" in
            apt)
                missing_tools+=("xz-utils")
                ;;
            dnf|yum|pacman)
                missing_tools+=("xz")
                ;;
        esac
    fi

    # 检查编译工具（Codex CLI 可能需要）
    if ! command -v gcc &> /dev/null; then
        case "$PKG_MANAGER" in
            apt)
                missing_tools+=("build-essential")
                ;;
            dnf|yum)
                missing_tools+=("gcc" "gcc-c++" "make")
                ;;
            pacman)
                missing_tools+=("base-devel")
                ;;
        esac
    fi

    if [[ ${#missing_tools[@]} -eq 0 ]]; then
        log_success "所有必要工具已安装。"
        return
    fi

    log_warn "检测到缺失的工具: ${missing_tools[*]}"
    log_info "正在安装缺失的工具..."

    case "$PKG_MANAGER" in
        apt)
            apt-get update -qq
            apt-get install -y -qq "${missing_tools[@]}"
            ;;
        dnf|yum)
            $PKG_MANAGER install -y -q "${missing_tools[@]}"
            ;;
        pacman)
            pacman -Sy --noconfirm --quiet "${missing_tools[@]}"
            ;;
    esac

    log_success "工具安装完成。"
}

# ============================================================
# Node.js 安装
# ============================================================

install_nodejs() {
    log_info "[2/8] 检查/安装 Node.js..."

    if command -v node &> /dev/null; then
        local node_version=$(node --version)
        log_success "Node.js 已安装: $node_version"

        if command -v npm &> /dev/null; then
            local npm_version=$(npm --version)
            log_success "npm 已安装: $npm_version"
            return 0
        else
            log_warn "检测到 Node.js 但 npm 不可用，将重新安装。"
        fi
    fi

    log_info "未检测到 Node.js，开始通过淘宝镜像下载预编译包..."

    # 检测 CPU 架构
    local arch=$(uname -m)
    local node_arch=""

    case "$arch" in
        x86_64)
            node_arch="linux-x64"
            ;;
        aarch64)
            node_arch="linux-arm64"
            ;;
        armv7l)
            node_arch="linux-armv7l"
            ;;
        ppc64le)
            node_arch="linux-ppc64le"
            ;;
        s390x)
            node_arch="linux-s390x"
            ;;
        *)
            log_error "不支持的 CPU 架构: $arch"
            log_error "支持的架构: x86_64, aarch64, armv7l, ppc64le, s390x"
            exit 1
            ;;
    esac

    log_info "检测到 CPU 架构: $arch → Node.js 架构: $node_arch"

    # 构建下载 URL
    local node_version="v${NODE_VERSION}"
    local node_filename="node-${node_version}-${node_arch}"
    local download_base="https://registry.npmmirror.com/-/binary/node/${node_version}"
    local download_url_xz="${download_base}/${node_filename}.tar.xz"
    local download_url_gz="${download_base}/${node_filename}.tar.gz"
    local temp_dir="/tmp/nodejs-install"
    local install_dir="/usr/local"

    # 创建临时目录
    rm -rf "$temp_dir"
    mkdir -p "$temp_dir"
    cd "$temp_dir"

    # 优先尝试下载 tar.xz 格式（体积更小）
    log_info "正在下载 Node.js ${node_version} (${node_arch})..."
    local download_success=false
    local downloaded_file=""

    if command -v curl &> /dev/null; then
        if curl -fSL --connect-timeout 10 --max-time 300 -o "${node_filename}.tar.xz" "$download_url_xz" 2>/dev/null; then
            downloaded_file="${node_filename}.tar.xz"
            download_success=true
            log_success "下载完成 (tar.xz 格式)"
        else
            log_warn "tar.xz 格式下载失败，尝试 tar.gz 格式..."
            if curl -fSL --connect-timeout 10 --max-time 300 -o "${node_filename}.tar.gz" "$download_url_gz" 2>/dev/null; then
                downloaded_file="${node_filename}.tar.gz"
                download_success=true
                log_success "下载完成 (tar.gz 格式)"
            fi
        fi
    elif command -v wget &> /dev/null; then
        if wget --timeout=10 --tries=3 -q -O "${node_filename}.tar.xz" "$download_url_xz" 2>/dev/null; then
            downloaded_file="${node_filename}.tar.xz"
            download_success=true
            log_success "下载完成 (tar.xz 格式)"
        else
            log_warn "tar.xz 格式下载失败，尝试 tar.gz 格式..."
            if wget --timeout=10 --tries=3 -q -O "${node_filename}.tar.gz" "$download_url_gz" 2>/dev/null; then
                downloaded_file="${node_filename}.tar.gz"
                download_success=true
                log_success "下载完成 (tar.gz 格式)"
            fi
        fi
    fi

    if [[ "$download_success" != true ]]; then
        log_error "Node.js 下载失败，请检查网络连接。"
        log_error "手动下载地址："
        log_error "  $download_url_xz"
        log_error "  $download_url_gz"
        rm -rf "$temp_dir"
        exit 1
    fi

    # 解压文件
    log_info "正在解压 Node.js..."
    if [[ "$downloaded_file" == *.tar.xz ]]; then
        tar -xJf "$downloaded_file" || {
            log_error "解压失败，请检查 xz 工具是否已安装。"
            rm -rf "$temp_dir"
            exit 1
        }
    else
        tar -xzf "$downloaded_file" || {
            log_error "解压失败。"
            rm -rf "$temp_dir"
            exit 1
        }
    fi

    # 移动文件到安装目录
    log_info "正在安装 Node.js 到 $install_dir ..."
    if [[ -d "$node_filename" ]]; then
        # 备份旧版本（如果存在）
        if [[ -d "${install_dir}/lib/node_modules" ]]; then
            log_warn "检测到旧版本 Node.js，正在备份..."
            mv "${install_dir}/lib/node_modules" "${install_dir}/lib/node_modules.backup.$(date +%s)" 2>/dev/null || true
        fi

        # 复制文件
        cp -rf "${node_filename}/bin/"* "${install_dir}/bin/" 2>/dev/null || true
        cp -rf "${node_filename}/lib/"* "${install_dir}/lib/" 2>/dev/null || true
        cp -rf "${node_filename}/include/"* "${install_dir}/include/" 2>/dev/null || true
        cp -rf "${node_filename}/share/"* "${install_dir}/share/" 2>/dev/null || true

        # 创建符号链接（确保命令可用）
        ln -sf "${install_dir}/bin/node" /usr/bin/node 2>/dev/null || true
        ln -sf "${install_dir}/bin/npm" /usr/bin/npm 2>/dev/null || true
        ln -sf "${install_dir}/bin/npx" /usr/bin/npx 2>/dev/null || true

        log_success "Node.js 安装完成。"
    else
        log_error "解压后未找到 Node.js 目录，安装失败。"
        rm -rf "$temp_dir"
        exit 1
    fi

    # 清理临时文件
    cd /
    rm -rf "$temp_dir"

    # 验证安装
    if command -v node &> /dev/null && command -v npm &> /dev/null; then
        log_success "Node.js $(node --version) 安装成功。"
        log_success "npm $(npm --version) 安装成功。"
    else
        log_error "Node.js 安装后验证失败。"
        log_error "请检查 PATH 环境变量是否包含: $install_dir/bin"
        log_error "或手动运行: export PATH=\"$install_dir/bin:\$PATH\""
        exit 1
    fi
}

# ============================================================
# npm 镜像配置
# ============================================================

config_npm_mirror() {
    log_info "[3/8] 配置 npm 淘宝镜像 (npmmirror)..."

    # 移除可能的代理设置
    npm config delete proxy 2>/dev/null || true
    npm config delete https-proxy 2>/dev/null || true

    # 移除 scope 专用源配置
    npm config delete @anthropic-ai:registry 2>/dev/null || true
    npm config delete @openai:registry 2>/dev/null || true
    npm config delete @google:registry 2>/dev/null || true

    # 设置淘宝镜像
    npm config set registry "$NPM_REGISTRY"

    local current_registry=$(npm config get registry)
    log_success "当前 npm 源: $current_registry"
}

# ============================================================
# Claude Code 安装
# ============================================================

install_claude_code() {
    log_info "[4/8] 安装 Claude Code (@anthropic-ai/claude-code)..."

    if command -v claude &> /dev/null; then
        log_success "检测到 Claude Code 已安装。"
        read -p "是否更新 Claude Code 到最新版本? (y/N): " -n 1 -r -t 5
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "跳过 Claude Code 更新。"
            return 0
        fi
    else
        log_info "未检测到 Claude Code。"
        read -p "是否安装 Claude Code? (Y/n，默认 Y): " -n 1 -r -t 5
        echo
        if [[ $REPLY =~ ^[Nn]$ ]]; then
            log_info "跳过 Claude Code 安装。"
            return 0
        fi
    fi

    log_info "安装/更新 Claude Code..."
    npm install -g @anthropic-ai/claude-code@latest --registry="$NPM_REGISTRY" || {
        log_error "Claude Code 安装失败，请检查网络连接。"
        return 1
    }

    log_success "Claude Code 安装/更新完成。"
}

# ============================================================
# Codex CLI 安装
# ============================================================

install_codex_cli() {
    log_info "[5/8] 安装 Codex CLI (@openai/codex)..."

    # 检查编译依赖
    if ! command -v gcc &> /dev/null; then
        log_warn "Codex CLI 需要编译工具，正在安装..."
        case "$PKG_MANAGER" in
            apt)
                apt-get install -y build-essential python3
                ;;
            dnf|yum)
                $PKG_MANAGER install -y gcc gcc-c++ make python3
                ;;
            pacman)
                pacman -Sy --noconfirm base-devel python
                ;;
        esac
    fi

    if command -v codex &> /dev/null; then
        log_success "检测到 Codex CLI 已安装。"
        read -p "是否更新 Codex CLI 到最新版本? (y/N): " -n 1 -r -t 5
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "跳过 Codex CLI 更新。"
            return 0
        fi
    else
        log_info "未检测到 Codex CLI。"
        read -p "是否安装 Codex CLI? (Y/n，默认 Y): " -n 1 -r -t 5
        echo
        if [[ $REPLY =~ ^[Nn]$ ]]; then
            log_info "跳过 Codex CLI 安装。"
            return 0
        fi
    fi

    log_info "安装/更新 Codex CLI（可能需要较长时间编译）..."
    npm install -g @openai/codex --registry="$NPM_REGISTRY" || {
        log_error "Codex CLI 安装失败。"
        log_error "可能原因: 1) 编译依赖缺失 2) 网络问题"
        return 1
    }

    log_success "Codex CLI 安装/更新完成。"
}

# ============================================================
# Gemini CLI 安装
# ============================================================

install_gemini_cli() {
    log_info "[6/8] 安装 Gemini CLI (@google/gemini-cli)..."

    if command -v gemini &> /dev/null; then
        log_success "检测到 Gemini CLI 已安装。"
        read -p "是否更新 Gemini CLI 到最新版本? (y/N): " -n 1 -r -t 5
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "跳过 Gemini CLI 更新。"
            return 0
        fi
    else
        log_info "未检测到 Gemini CLI。"
        read -p "是否安装 Gemini CLI? (Y/n，默认 Y): " -n 1 -r -t 5
        echo
        if [[ $REPLY =~ ^[Nn]$ ]]; then
            log_info "跳过 Gemini CLI 安装。"
            return 0
        fi
    fi

    log_info "安装/更新 Gemini CLI..."
    npm install -g @google/gemini-cli@latest --registry="$NPM_REGISTRY" || {
        log_error "Gemini CLI 安装失败，请检查网络连接。"
        return 1
    }

    log_success "Gemini CLI 安装/更新完成。"
}

# ============================================================
# Droid CLI 安装
# ============================================================

install_droid_cli() {
    log_info "[7/8] 安装 Droid CLI (factory.ai)..."

    if command -v droid &> /dev/null; then
        log_success "检测到 Droid CLI 已安装。"
        read -p "是否通过官方脚本重新安装/更新? (y/N): " -n 1 -r -t 5
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "跳过 Droid CLI 更新。"
            return 0
        fi
    else
        log_info "未检测到 Droid CLI。"
        read -p "是否通过官方脚本安装? (y/N): " -n 1 -r -t 5
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "跳过 Droid CLI 安装。"
            return 0
        fi
    fi

    log_info "通过官方脚本安装/更新 Droid CLI..."

    if command -v curl &> /dev/null; then
        curl -fsSL "$DROID_INSTALL_URL" | bash || {
            log_error "Droid CLI 安装失败，请检查网络或稍后重试。"
            return 1
        }
    elif command -v wget &> /dev/null; then
        wget -qO- "$DROID_INSTALL_URL" | bash || {
            log_error "Droid CLI 安装失败，请检查网络或稍后重试。"
            return 1
        }
    else
        log_error "需要 curl 或 wget 来下载 Droid CLI 安装脚本。"
        return 1
    fi

    log_success "Droid CLI 安装/更新完成。"
}

# ============================================================
# OpenClaw 安装
# ============================================================

install_openclaw() {
    log_info "安装 OpenClaw CLI (openclaw)..."

    if command -v openclaw &> /dev/null; then
        log_success "检测到 OpenClaw 已安装。"
        read -p "是否更新 OpenClaw 到最新版本? (Y/n，默认 Y): " -n 1 -r -t 5
        echo
        if [[ $REPLY =~ ^[Nn]$ ]]; then
            log_info "跳过 OpenClaw 更新。"
            return 0
        fi
    else
        log_info "未检测到 OpenClaw CLI。"
        read -p "是否安装 OpenClaw? (Y/n，默认 Y): " -n 1 -r -t 5
        echo
        if [[ $REPLY =~ ^[Nn]$ ]]; then
            log_info "跳过 OpenClaw 安装。"
            return 0
        fi
    fi

    log_info "安装/更新 OpenClaw..."
    npm install -g openclaw@latest --registry="$NPM_REGISTRY" || {
        log_error "OpenClaw 安装失败，请检查网络连接。"
        return 1
    }

    log_success "OpenClaw 安装/更新完成。"
}

# ============================================================
# Git 安装
# ============================================================

install_git() {
    log_info "[8/8] 安装 Git (推荐)..."

    if command -v git &> /dev/null; then
        local git_version=$(git --version)
        log_success "Git 已安装: $git_version"
        return 0
    fi

    log_info "未检测到 Git，开始安装..."

    case "$PKG_MANAGER" in
        apt)
            # 使用官方 PPA 获取最新版本
            apt-get install -y software-properties-common
            add-apt-repository -y ppa:git-core/ppa 2>/dev/null || true
            apt-get update -qq
            apt-get install -y git
            ;;
        dnf|yum)
            $PKG_MANAGER install -y git
            ;;
        pacman)
            pacman -Sy --noconfirm git
            ;;
    esac

    if command -v git &> /dev/null; then
        log_success "Git $(git --version) 安装成功。"
    else
        log_error "Git 安装失败，请手动安装。"
    fi
}

# ============================================================
# Token 配置
# ============================================================

config_tokens() {
    log_info "[9/9] 配置 API Base 与各 CLI 的 Token (API Key)..."

    read -p "请输入 API Base URL (留空使用默认 https://api.share-ai.woolen.wang): " API_BASE
    API_BASE=${API_BASE:-"https://api.share-ai.woolen.wang"}

    read -p "请输入 ShareAI API Token (例如 sk-xxxx)，留空则仅安装 CLI 而不配置 Token: " API_KEY

    log_success "API Token: ${API_KEY:0:10}...${API_KEY: -5}"

    if [[ -z "$API_KEY" ]]; then
        log_warn "未输入 Token，本次仅完成 CLI 安装，未配置任何 Token 或配置文件。"
        return 0
    fi

    # 配置 Claude Code
    config_claude_code "$API_BASE" "$API_KEY"

    # 配置 Codex CLI
    config_codex_cli "$API_BASE" "$API_KEY"

    # 配置 Gemini CLI
    config_gemini_cli "$API_BASE" "$API_KEY"

    # 配置 OpenClaw
    config_openclaw_cli "$API_BASE" "$API_KEY"

    # 配置环境变量
    config_environment_variables "$API_BASE" "$API_KEY"

    log_success "Token 和配置文件已为 Claude Code / Codex / Gemini 统一配置完成。"
    log_warn "注意: 新的环境变量需要重新加载 shell 配置文件后生效："
    log_warn "  source ~/.bashrc   # 或 source ~/.zshrc"
}

config_claude_code() {
    local api_base="$1"
    local api_key="$2"
    local claude_dir="${HOME}/.claude"
    local claude_settings="${claude_dir}/settings.json"

    mkdir -p "$claude_dir"

    if [[ -f "$claude_settings" ]] && [[ -s "$claude_settings" ]]; then
        if grep -q "ANTHROPIC_BASE_URL" "$claude_settings" 2>/dev/null; then
            log_info "检测到已有 Claude Code 配置文件且已包含 ANTHROPIC_BASE_URL: $claude_settings"
        else
            log_warn "检测到已有 Claude Code 配置文件，但未检测到关键字段 ANTHROPIC_BASE_URL: $claude_settings"
        fi

        read -p "是否覆盖该 Claude Code 配置文件? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "保留原有 Claude Code 配置文件，跳过自动写入。"
            return 0
        fi
    fi

    cat > "$claude_settings" <<EOF
{
  "env": {
    "ANTHROPIC_AUTH_TOKEN": "$api_key",
    "ANTHROPIC_BASE_URL": "$api_base",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
  },
  "statusLine": {
    "type": "command",
    "command": "npx -y ccstatusline@latest",
    "padding": 0
  },
  "permissions": {
    "allow": [],
    "deny": []
  }
}
EOF

    log_success "已写入 Claude Code 配置文件: $claude_settings"
}

config_codex_cli() {
    local api_base="$1"
    local api_key="$2"
    local codex_dir="${HOME}/.codex"
    local codex_config="${codex_dir}/config.toml"
    local codex_auth="${codex_dir}/auth.json"

    mkdir -p "$codex_dir"

    if [[ -f "$codex_config" ]] && [[ -s "$codex_config" ]]; then
        if grep -q "base_url" "$codex_config" 2>/dev/null; then
            log_info "检测到已有 Codex CLI 配置文件且已包含 base_url: $codex_config"
        else
            log_warn "检测到已有 Codex CLI 配置文件，但未检测到关键字段 base_url: $codex_config"
        fi

        read -p "是否覆盖该 Codex CLI 配置文件? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "保留原有 Codex CLI 配置文件，跳过自动写入。"
            return 0
        fi
    fi

    cat > "$codex_config" <<EOF
disable_response_storage = true
model = "gpt-5.2"
model_reasoning_effort = "high"
model_provider = "share-ai"
sandbox_mode = "danger-full-access"
windows_wsl_setup_acknowledged = true
base_instructions = "Always prefer built-in tools (read_file, list_dir, grep_files) over shell commands for file operations."

[experimental]
use_freeform_apply_patch = true
use_unified_exec_tool = true

[features]
apply_patch_freeform = true
ghost_commit = true
plan_tool = true
rmcp_client = true
streamable_shell = false
unified_exec = false
view_image_tool = true
web_search_request = true
enable_experimental_windows_sandbox = false
experimental_sandbox_command_assessment = true
parallel = true

[model_providers.share-ai]
base_url = "$api_base/v1"
name = "share-ai"
requires_openai_auth = true
wire_api = "responses"

[sandbox_workspace_write]
network_access = true
EOF

    cat > "$codex_auth" <<EOF
{
  "OPENAI_API_KEY": "$api_key"
}
EOF

    log_success "已写入 Codex CLI 配置文件: $codex_config"
    log_success "已写入 Codex CLI 认证文件: $codex_auth"
}

config_gemini_cli() {
    local api_base="$1"
    local api_key="$2"
    local gemini_dir="${HOME}/.gemini"
    local gemini_env="${gemini_dir}/.env"
    local gemini_settings="${gemini_dir}/settings.json"

    mkdir -p "$gemini_dir"

    if [[ -f "$gemini_env" ]] && [[ -s "$gemini_env" ]]; then
        if grep -q "GEMINI_API_BASE_URL" "$gemini_env" 2>/dev/null; then
            log_info "检测到已有 Gemini CLI 配置文件且已包含 GEMINI_API_BASE_URL: $gemini_env"
        else
            log_warn "检测到已有 Gemini CLI 配置文件，但未检测到关键字段 GEMINI_API_BASE_URL: $gemini_env"
        fi

        read -p "是否覆盖该 Gemini CLI 配置文件? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "保留原有 Gemini CLI 配置文件，跳过自动写入。"
            return 0
        fi
    fi

    cat > "$gemini_env" <<EOF
GEMINI_API_KEY=$api_key
GOOGLE_GEMINI_BASE_URL=$api_base
EOF

    cat > "$gemini_settings" <<EOF
{
  "security": {
    "auth": {
      "selectedType": "gemini-api-key"
    },
    "folderTrust": {
      "enabled": true
    }
  }
}
EOF

    log_success "已写入 Gemini CLI 环境变量文件: $gemini_env"
    log_success "已写入 Gemini CLI 配置文件: $gemini_settings"

    # 生成安装 ID
    local install_id_file="${gemini_dir}/installation_id"
    if [[ ! -f "$install_id_file" ]]; then
        local install_id=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || echo "$(date +%s)-$(hostname)-$$")
        echo "$install_id" > "$install_id_file"
        log_success "已生成 Gemini CLI 安装 ID: $install_id"
    else
        log_info "检测到已有 Gemini CLI 安装 ID 文件: $install_id_file"
    fi
}

config_openclaw_cli() {
    local api_base="$1"
    local api_key="$2"
    local openclaw_dir="${HOME}/.openclaw"
    local openclaw_config="${openclaw_dir}/openclaw.json"

    if ! command -v openclaw &> /dev/null; then
        log_info "未检测到 OpenClaw CLI，跳过 OpenClaw 配置文件写入。"
        return 0
    fi

    mkdir -p "$openclaw_dir"

    if [[ -f "$openclaw_config" ]] && [[ -s "$openclaw_config" ]]; then
        if grep -q "shareai" "$openclaw_config" 2>/dev/null; then
            log_info "检测到已有 OpenClaw 配置文件且已包含 shareai 配置: $openclaw_config"
        else
            log_warn "检测到已有 OpenClaw 配置文件: $openclaw_config"
        fi

        read -p "是否覆盖该 OpenClaw 配置文件? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "保留原有 OpenClaw 配置文件，跳过自动写入。"
            return 0
        fi
    fi

    # 生成时间戳和随机 Token
    local now_ts=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
    local gw_token=$(openssl rand -hex 24 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null | tr -d '-' | head -c 48 || echo "$(date +%s)$(hostname)$$" | md5sum | head -c 48)
    local home_dir="$HOME"

    cat > "$openclaw_config" <<EOF
{
  "meta": {
    "lastTouchedVersion": "2026.2.25",
    "lastTouchedAt": "$now_ts"
  },
  "wizard": {
    "lastRunAt": "$now_ts",
    "lastRunVersion": "2026.2.6-3",
    "lastRunCommand": "onboard",
    "lastRunMode": "local"
  },
  "models": {
    "mode": "merge",
    "providers": {
      "shareai-openai": {
        "baseUrl": "$api_base/v1",
        "apiKey": "$api_key",
        "api": "openai-responses",
        "models": [
          {
            "id": "gpt-5.2",
            "name": "gpt-5.2",
            "reasoning": true
          },
          {
            "id": "gpt-5.3-codex",
            "name": "gpt-5.3-codex",
            "reasoning": true
          },
          {
            "id": "gpt-5.4",
            "name": "gpt-5.4",
            "reasoning": true,
            "input": ["text"],
            "cost": {
              "input": 0,
              "output": 0,
              "cacheRead": 0,
              "cacheWrite": 0
            },
            "contextWindow": 1000000,
            "maxTokens": 8192
          }
        ]
      },
      "shareai-claude": {
        "baseUrl": "$api_base/",
        "apiKey": "$api_key",
        "api": "anthropic-messages",
        "models": [
          {
            "id": "claude-opus-4-6",
            "name": "claude-opus-4-6",
            "reasoning": true,
            "maxTokens": 8192
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "shareai-openai/gpt-5.4"
      },
      "workspace": "$home_dir/.openclaw/workspace",
      "compaction": {
        "reserveTokensFloor": 300000,
        "memoryFlush": {
          "enabled": true,
          "softThresholdTokens": 20000
        }
      },
      "timeoutSeconds": 1800,
      "maxConcurrent": 10,
      "subagents": {
        "maxConcurrent": 20,
        "maxSpawnDepth": 2,
        "maxChildrenPerAgent": 5,
        "runTimeoutSeconds": 900
      }
    }
  },
  "tools": {
    "profile": "full"
  },
  "messages": {
    "ackReactionScope": "group-mentions"
  },
  "commands": {
    "native": "auto",
    "nativeSkills": "auto",
    "restart": true,
    "ownerDisplay": "raw"
  },
  "skills": {
    "install": {
      "nodeManager": "npm"
    }
  },
  "gateway": {
    "port": 18789,
    "mode": "local",
    "bind": "loopback",
    "auth": {
      "mode": "token",
      "token": "$gw_token"
    }
  }
}
EOF

    log_success "已写入 OpenClaw 配置文件: $openclaw_config"
}

config_environment_variables() {
    local api_base="$1"
    local api_key="$2"

    # 检测用户使用的 shell
    local shell_rc=""
    if [[ -n "$ZSH_VERSION" ]] || [[ "$SHELL" == */zsh ]]; then
        shell_rc="${HOME}/.zshrc"
    else
        shell_rc="${HOME}/.bashrc"
    fi

    log_info "配置环境变量到 $shell_rc ..."

    # 检查是否已配置
    if grep -q "# WQuant AI CLI Environment Variables" "$shell_rc" 2>/dev/null; then
        log_warn "检测到已有 WQuant 环境变量配置，将更新配置。"
        # 删除旧配置块
        sed -i '/# WQuant AI CLI Environment Variables/,/# End of WQuant AI CLI Environment Variables/d' "$shell_rc"
    fi

    # 添加新配置
    cat >> "$shell_rc" <<EOF

# WQuant AI CLI Environment Variables
export ANTHROPIC_BASE_URL="$api_base"
export ANTHROPIC_AUTH_TOKEN="$api_key"
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC="1"
export OPENAI_BASE_URL="$api_base"
export OPENAI_API_KEY="$api_key"
export CODE_ASSIST_ENDPOINT="$api_base"
export GEMINI_API_KEY="$api_key"
export GOOGLE_GEMINI_BASE_URL="$api_base"
export GOOGLE_GENAI_USE_GCA="true"
# End of WQuant AI CLI Environment Variables
EOF

    log_success "环境变量配置完成。"
    log_warn "请运行以下命令使环境变量生效："
    log_warn "  source $shell_rc"
}

# ============================================================
# 主函数
# ============================================================

main() {
    echo "=============================================="
    echo "WQuant AI CLI 一键安装脚本 (Linux 版)"
    echo "=============================================="
    echo ""

    # Phase 1: 系统检测
    check_root_privileges
    detect_os
    detect_package_manager
    check_required_tools

    echo ""
    log_info ">>> 开始环境检查与安装..."
    echo ""

    # Phase 2: Node.js 环境
    install_nodejs
    config_npm_mirror

    echo ""

    # Phase 3: CLI 工具安装
    install_claude_code
    echo ""

    install_codex_cli
    echo ""

    install_gemini_cli
    echo ""

    install_droid_cli
    echo ""

    install_openclaw
    echo ""

    # Phase 4: Git 安装
    install_git
    echo ""

    # Phase 5: Token 配置
    config_tokens

    echo ""
    echo "=============================================="
    log_success "所有任务执行完毕！"
    echo "=============================================="
    echo ""
    echo "使用说明："
    echo "1. 请先加载环境变量: source ~/.bashrc (或 source ~/.zshrc)"
    echo "2. 验证安装:"
    echo "   - claude --version"
    echo "   - codex --version"
    echo "   - gemini --version"
    echo "   - droid --version"
    echo "   - openclaw --version"
    echo "3. 如命令无法识别，请检查 npm 全局安装路径是否在 PATH 中："
    echo "   - npm config get prefix"
    echo "   - export PATH=\"\$(npm config get prefix)/bin:\$PATH\""
    echo "4. 使用 CLI 时如需代理，请自行配置系统代理或环境变量 (HTTP_PROXY / HTTPS_PROXY)。"
    echo "5. 若要登录官方账号，请根据各 CLI 文档执行对应登录命令。"
    echo ""
    echo "=============================================="
}

# 执行主函数
main "$@"
