#!/bin/bash
# ============================================================================
# Hermes Agent 安装器（中国大陆镜像版）
# ============================================================================
# Installation script for Linux, macOS, and Android/Termux.
# Prefers CNB.cool Git mirror first, then falls back to source archives / upstream.
#
# Usage:
#   curl -fsSL https://hermes.ver0.cn/install.sh | bash
#
# Or with options:
#   curl -fsSL https://hermes.ver0.cn/install.sh | bash -s -- --skip-setup
#   curl -fsSL https://hermes.ver0.cn/install.sh | bash -s -- --with-browser
#
# ============================================================================

set -e

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
BOLD='\033[1m'

# Base configuration
MIRROR_BASE_URL="${HERMES_MIRROR_BASE_URL:-https://hermes.ver0.cn}"
UPSTREAM_REPO_URL="https://github.com/NousResearch/hermes-agent.git"
UPSTREAM_TARBALL_BASE="https://github.com/NousResearch/hermes-agent/archive/refs/heads"
DEFAULT_GIT_MIRROR_URL="https://cnb.cool/hermesagent-cn/hermes-agent-cn-mirror.git"
GIT_MIRROR_URL="${HERMES_GIT_MIRROR_URL:-$DEFAULT_GIT_MIRROR_URL}"

HERMES_HOME="$HOME/.hermes"
INSTALL_DIR="${HERMES_INSTALL_DIR:-$HERMES_HOME/hermes-agent}"
PYTHON_VERSION="3.11"
NODE_VERSION="22"
AGENT_BROWSER_VERSION="${HERMES_AGENT_BROWSER_VERSION:-0.13.0}"

PIP_INDEX_URL_DEFAULT="${HERMES_PIP_INDEX_URL:-https://pypi.tuna.tsinghua.edu.cn/simple}"
PIP_FALLBACK_INDEX_URLS_DEFAULT="${HERMES_PIP_FALLBACK_INDEX_URLS:-https://mirrors.aliyun.com/pypi/simple https://pypi.mirrors.ustc.edu.cn/simple https://pypi.org/simple}"
NPM_REGISTRY_DEFAULT="${HERMES_NPM_REGISTRY:-https://registry.npmmirror.com}"
NODE_DIST_MIRROR_DEFAULT="${HERMES_NODE_DIST_MIRROR:-https://npmmirror.com/mirrors/node}"
UV_INSTALLER_URL_DEFAULT="${HERMES_UV_INSTALLER_URL:-$MIRROR_BASE_URL/third-party/uv/install.sh}"
UV_INSTALLER_GITHUB_BASE_URL_DEFAULT="${HERMES_UV_GITHUB_BASE_URL:-$MIRROR_BASE_URL/third-party/github}"
UV_PYTHON_INSTALL_MIRROR_DEFAULT="${HERMES_UV_PYTHON_MIRROR:-$MIRROR_BASE_URL/third-party/python-build-standalone/releases/download}"
PLAYWRIGHT_DOWNLOAD_HOST_CONFIG="${HERMES_PLAYWRIGHT_DOWNLOAD_HOST:-}"

# Options
USE_VENV=true
RUN_SETUP=true
BRANCH="main"
INSTALL_BROWSER_TOOLS=false
INSTALL_WHATSAPP_BRIDGE=false
INSTALL_NODE_RUNTIME=false
INSTALL_OPTIONAL_EXTRAS=false

# Detect non-interactive mode (e.g. curl | bash)
if [ -t 0 ]; then
    IS_INTERACTIVE=true
else
    IS_INTERACTIVE=false
fi

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --no-venv)
            USE_VENV=false
            shift
            ;;
        --skip-setup)
            RUN_SETUP=false
            shift
            ;;
        --branch)
            BRANCH="$2"
            shift 2
            ;;
        --dir)
            INSTALL_DIR="$2"
            shift 2
            ;;
        --mirror)
            MIRROR_BASE_URL="$2"
            shift 2
            ;;
        --with-node)
            INSTALL_NODE_RUNTIME=true
            shift
            ;;
        --with-browser)
            INSTALL_NODE_RUNTIME=true
            INSTALL_BROWSER_TOOLS=true
            shift
            ;;
        --with-whatsapp)
            INSTALL_NODE_RUNTIME=true
            INSTALL_WHATSAPP_BRIDGE=true
            shift
            ;;
        --with-optional-extras)
            INSTALL_OPTIONAL_EXTRAS=true
            shift
            ;;
        --full)
            INSTALL_NODE_RUNTIME=true
            INSTALL_BROWSER_TOOLS=true
            INSTALL_WHATSAPP_BRIDGE=true
            INSTALL_OPTIONAL_EXTRAS=true
            shift
            ;;
        -h|--help)
            echo "Hermes Agent 安装器（中国大陆镜像版）"
            echo ""
            echo "用法：install.sh [选项]"
            echo ""
            echo "可用选项："
            echo "  --no-venv         不创建虚拟环境"
            echo "  --skip-setup      跳过交互式配置向导"
            echo "  --branch NAME     要安装的 Git 分支（默认：main）"
            echo "  --dir PATH        安装目录（默认：~/.hermes/hermes-agent）"
            echo "  --mirror URL      覆盖镜像基础地址（默认指向 hermes.ver0.cn）"
            echo "  --with-node       仅安装 Node.js 运行时"
            echo "  --with-browser    尽力安装浏览器相关 JS 依赖"
            echo "  --with-whatsapp   显示 WhatsApp 桥接后续安装说明"
            echo "  --with-optional-extras 安装完整 Python 扩展依赖（耗时更长）"
            echo "  --full            等同于 --with-browser --with-whatsapp"
            echo "  -h, --help        显示帮助"
            exit 0
            ;;
        *)
            echo "未知参数：$1"
            exit 1
            ;;
    esac
done

# ==========================================================================
# Helper functions
# ==========================================================================

print_banner() {
    echo ""
    echo -e "${MAGENTA}${BOLD}"
    echo "┌─────────────────────────────────────────────────────────┐"
    echo "│        ⚕ Hermes Agent 安装器 · hermes.ver0.cn          │"
    echo "├─────────────────────────────────────────────────────────┤"
    echo "│  国内镜像加速安装                                       │"
    echo "│  镜像站: https://hermes.ver0.cn                         │"
    echo "└─────────────────────────────────────────────────────────┘"
    echo -e "${NC}"
}

log_info() {
    echo -e "${CYAN}→${NC} $1"
}

log_success() {
    echo -e "${GREEN}✓${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}⚠${NC} $1"
}

log_error() {
    echo -e "${RED}✗${NC} $1"
}

print_step() {
    echo ""
    echo -e "${CYAN}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "${CYAN}${BOLD}$1${NC}"
    echo -e "${CYAN}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}

is_termux() {
    [ -n "${TERMUX_VERSION:-}" ] || [[ "${PREFIX:-}" == *"com.termux/files/usr"* ]]
}

get_command_link_dir() {
    if is_termux && [ -n "${PREFIX:-}" ]; then
        echo "$PREFIX/bin"
    else
        echo "$HOME/.local/bin"
    fi
}

get_command_link_display_dir() {
    if is_termux && [ -n "${PREFIX:-}" ]; then
        echo '$PREFIX/bin'
    else
        echo '~/.local/bin'
    fi
}

get_hermes_command_path() {
    local link_dir
    link_dir="$(get_command_link_dir)"
    if [ -x "$link_dir/hermes" ]; then
        echo "$link_dir/hermes"
    else
        echo "hermes"
    fi
}

configure_network_defaults() {
    export PIP_INDEX_URL="${PIP_INDEX_URL:-$PIP_INDEX_URL_DEFAULT}"
    export UV_DEFAULT_INDEX="${UV_DEFAULT_INDEX:-$PIP_INDEX_URL}"
    export NPM_CONFIG_REGISTRY="${NPM_CONFIG_REGISTRY:-$NPM_REGISTRY_DEFAULT}"
    export PIP_DISABLE_PIP_VERSION_CHECK=1
    export PIP_ROOT_USER_ACTION=ignore
}

get_pip_index_candidates() {
    {
        printf '%s\n' "${PIP_INDEX_URL:-$PIP_INDEX_URL_DEFAULT}"
        for mirror in $PIP_FALLBACK_INDEX_URLS_DEFAULT; do
            printf '%s\n' "$mirror"
        done
    } | awk 'NF && !seen[$0]++'
}

pip_install_with_fallback() {
    local pip_python="$1"
    shift

    local pip_log mirror pip_pid progress_pid elapsed
    pip_log="$(mktemp)"

    while IFS= read -r mirror; do
        [ -z "$mirror" ] && continue
        log_info "正在尝试 pip 镜像：$mirror"
        PIP_INDEX_URL="$mirror" "$pip_python" -m pip "$@" >"$pip_log" 2>&1 &
        pip_pid=$!

        (
            elapsed=0
            while kill -0 "$pip_pid" 2>/dev/null; do
                sleep 15
                elapsed=$((elapsed + 15))
                if kill -0 "$pip_pid" 2>/dev/null; then
                    log_info "pip 仍在处理中（已等待 ${elapsed} 秒），请耐心稍候..."
                fi
            done
        ) &
        progress_pid=$!

        wait "$pip_pid"
        local pip_exit=$?
        kill "$progress_pid" 2>/dev/null || true
        wait "$progress_pid" 2>/dev/null || true

        if [ "$pip_exit" -eq 0 ]; then
            export PIP_INDEX_URL="$mirror"
            export UV_DEFAULT_INDEX="$mirror"
            rm -f "$pip_log"
            return 0
        fi

        log_warn "当前镜像安装失败，准备切换下一个镜像..."
        tail -5 "$pip_log" | while IFS= read -r line; do
            [ -n "$line" ] && log_warn "  $line"
        done
    done < <(get_pip_index_candidates)

    log_error "所有 pip 镜像都尝试失败了"
    rm -f "$pip_log"
    return 1
}

get_source_tarball_urls() {
    local custom="${HERMES_SOURCE_TARBALL_URL:-}"
    local urls=()
    local cache_bust_query="?v=2026.04.16"

    if [ -n "$custom" ]; then
        urls+=("$custom")
    fi

    urls+=(
        "$MIRROR_BASE_URL/hermes-agent-${BRANCH}.tar.gz${cache_bust_query}"
        "$MIRROR_BASE_URL/hermes-agent-main.tar.gz${cache_bust_query}"
        "$UPSTREAM_TARBALL_BASE/${BRANCH}.tar.gz"
    )

    printf '%s\n' "${urls[@]}"
}

download_to_file() {
    local dest="$1"
    shift
    local url
    for url in "$@"; do
        [ -z "$url" ] && continue
        log_info "正在尝试下载：$url"
        if curl --connect-timeout 15 --retry 2 --retry-delay 1 -fL "$url" -o "$dest"; then
            return 0
        fi
    done
    return 1
}

download_to_stdout() {
    local url
    for url in "$@"; do
        [ -z "$url" ] && continue
        log_info "正在尝试下载：$url"
        if curl --connect-timeout 15 --retry 2 --retry-delay 1 -fsSL "$url"; then
            return 0
        fi
    done
    return 1
}

python_meets_requirement() {
    local candidate="$1"
    "$candidate" - <<'PY' >/dev/null 2>&1
import sys
raise SystemExit(0 if sys.version_info >= (3, 11) else 1)
PY
}

get_python_minor_version() {
    "$PYTHON_PATH" - <<'PY' 2>/dev/null
import sys
print(f"{sys.version_info.major}.{sys.version_info.minor}")
PY
}

find_system_python() {
    local candidates=(python3.13 python3.12 python3.11 python3 python)
    local candidate path
    for candidate in "${candidates[@]}"; do
        if command -v "$candidate" >/dev/null 2>&1; then
            path="$(command -v "$candidate")"
            if python_meets_requirement "$path"; then
                PYTHON_PATH="$path"
                PYTHON_FOUND_VERSION="$($PYTHON_PATH --version 2>/dev/null)"
                return 0
            fi
        fi
    done
    return 1
}

ensure_python_venv_package() {
    if [ "$DISTRO" != "ubuntu" ] && [ "$DISTRO" != "debian" ]; then
        return 1
    fi

    local py_minor packages=() pkg
    py_minor="$(get_python_minor_version)"

    if [ -n "$py_minor" ]; then
        packages+=("python${py_minor}-venv")
    fi
    packages+=("python3-venv")

    for pkg in "${packages[@]}"; do
        if dpkg -s "$pkg" >/dev/null 2>&1; then
            return 0
        fi
    done

    log_warn "检测到系统 Python 缺少虚拟环境组件（venv / ensurepip）"
    log_info "正在尝试自动安装：${packages[*]}"
    log_info "这一步可能需要几十秒，请耐心等待。"

    if [ "$(id -u)" -eq 0 ]; then
        log_info "正在以 root 身份刷新软件源..."
        apt-get update -qq || true
        for pkg in "${packages[@]}"; do
            log_info "正在安装 $pkg ..."
            if apt-get install -y -qq "$pkg" >/dev/null 2>&1; then
                log_success "已安装 $pkg"
                return 0
            fi
        done
        return 1
    fi

    if command -v sudo >/dev/null 2>&1 && sudo -n true 2>/dev/null; then
        log_info "检测到免密 sudo，正在自动刷新软件源..."
        sudo apt-get update -qq || true
        for pkg in "${packages[@]}"; do
            log_info "正在通过 sudo 安装 $pkg ..."
            if sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get install -y -qq "$pkg" >/dev/null 2>&1; then
                log_success "已安装 $pkg"
                return 0
            fi
        done
        return 1
    fi

    if command -v sudo >/dev/null 2>&1 && [ -e /dev/tty ]; then
        echo ""
        log_info "当前系统 Python 无法创建虚拟环境，需要安装 venv 组件。"
        log_info "Hermes 本体不需要长期 root 权限；这里只会调用一次 apt 安装必要软件包。"
        read -p "现在自动安装 venv 组件吗？[Y/n] " -n 1 -r < /dev/tty
        echo
        if [[ $REPLY =~ ^[Nn]$ ]]; then
            return 1
        fi
        log_info "正在通过 sudo 刷新软件源..."
        sudo apt-get update -qq < /dev/tty || true
        for pkg in "${packages[@]}"; do
            log_info "正在通过 sudo 安装 $pkg ..."
            if sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get install -y -qq "$pkg" < /dev/tty >/dev/null 2>&1; then
                log_success "已安装 $pkg"
                return 0
            fi
        done
    fi

    return 1
}

show_manual_install_hint() {
    local pkg="$1"
    log_info "如需手动安装 $pkg："
    case "$OS" in
        linux)
            case "$DISTRO" in
                ubuntu|debian) log_info "  sudo apt install $pkg" ;;
                fedora)        log_info "  sudo dnf install $pkg" ;;
                arch)          log_info "  sudo pacman -S $pkg" ;;
                *)             log_info "  请使用系统包管理器，或访问项目主页手动安装" ;;
            esac
            ;;
        android)
            log_info "  pkg install $pkg"
            ;;
        macos)
            log_info "  brew install $pkg"
            ;;
    esac
}

# ==========================================================================
# System detection
# ==========================================================================

detect_os() {
    case "$(uname -s)" in
        Linux*)
            if is_termux; then
                OS="android"
                DISTRO="termux"
            else
                OS="linux"
                if [ -f /etc/os-release ]; then
                    . /etc/os-release
                    DISTRO="$ID"
                else
                    DISTRO="unknown"
                fi
            fi
            ;;
        Darwin*)
            OS="macos"
            DISTRO="macos"
            ;;
        CYGWIN*|MINGW*|MSYS*)
            OS="windows"
            DISTRO="windows"
            log_error "检测到 Windows，请改用 PowerShell 安装器："
            log_info "  irm https://hermes.ver0.cn/install.ps1 | iex"
            exit 1
            ;;
        *)
            OS="unknown"
            DISTRO="unknown"
            log_warn "无法识别当前操作系统"
            ;;
    esac

    log_success "已识别系统：$OS ($DISTRO)"
}

# ==========================================================================
# Dependency checks
# ==========================================================================

install_uv() {
    if [ "$DISTRO" = "termux" ]; then
        UV_CMD=""
        return 0
    fi

    log_info "正在检查 uv 包管理器..."

    if command -v uv >/dev/null 2>&1; then
        UV_CMD="uv"
        log_success "已找到 uv（$($UV_CMD --version 2>/dev/null)）"
        return 0
    fi

    if [ -x "$HOME/.local/bin/uv" ]; then
        UV_CMD="$HOME/.local/bin/uv"
        log_success "已在 ~/.local/bin 找到 uv（$($UV_CMD --version 2>/dev/null)）"
        return 0
    fi

    if [ -x "$HOME/.cargo/bin/uv" ]; then
        UV_CMD="$HOME/.cargo/bin/uv"
        log_success "已在 ~/.cargo/bin 找到 uv（$($UV_CMD --version 2>/dev/null)）"
        return 0
    fi

    log_info "正在安装 uv（优先镜像，失败后回退上游）..."
    export UV_INSTALLER_GITHUB_BASE_URL="${UV_INSTALLER_GITHUB_BASE_URL:-$UV_INSTALLER_GITHUB_BASE_URL_DEFAULT}"

    local uv_installer_tmp uv_installer_ok=false uv_installer_url
    uv_installer_tmp="$(mktemp)"
    for uv_installer_url in "$UV_INSTALLER_URL_DEFAULT" "https://astral.sh/uv/install.sh"; do
        [ -z "$uv_installer_url" ] && continue
        log_info "正在下载 uv 安装脚本：$uv_installer_url"
        if curl --connect-timeout 15 --retry 2 --retry-delay 1 -fL "$uv_installer_url" -o "$uv_installer_tmp"; then
            uv_installer_ok=true
            break
        fi
    done

    if [ "$uv_installer_ok" = true ] && sh "$uv_installer_tmp" 2>/dev/null; then
        if [ -x "$HOME/.local/bin/uv" ]; then
            UV_CMD="$HOME/.local/bin/uv"
        elif [ -x "$HOME/.cargo/bin/uv" ]; then
            UV_CMD="$HOME/.cargo/bin/uv"
        elif command -v uv >/dev/null 2>&1; then
            UV_CMD="uv"
        else
            log_error "uv 已安装，但当前 PATH 中找不到它"
            log_info "请将 ~/.local/bin 加入 PATH 后重新运行"
            exit 1
        fi
        log_success "uv 安装完成（$($UV_CMD --version 2>/dev/null)）"
    else
        log_error "安装 uv 失败"
        log_info "如需手动安装，请访问：https://docs.astral.sh/uv/getting-started/installation/"
        rm -f "$uv_installer_tmp"
        exit 1
    fi
    rm -f "$uv_installer_tmp"
}

check_python() {
    if [ "$DISTRO" = "termux" ]; then
        log_info "正在检查 Termux Python..."
        if command -v python >/dev/null 2>&1; then
            PYTHON_PATH="$(command -v python)"
            if python_meets_requirement "$PYTHON_PATH"; then
                PYTHON_FOUND_VERSION="$($PYTHON_PATH --version 2>/dev/null)"
                log_success "已找到 Python：$PYTHON_FOUND_VERSION"
                return 0
            fi
        fi

        log_info "正在通过 pkg 安装 Python..."
        pkg install -y python >/dev/null
        PYTHON_PATH="$(command -v python)"
        PYTHON_FOUND_VERSION="$($PYTHON_PATH --version 2>/dev/null)"
        log_success "Python 安装完成：$PYTHON_FOUND_VERSION"
        return 0
    fi

    log_info "正在检查可用的系统 Python（>= 3.11）..."
    if find_system_python; then
        log_success "已找到 Python：$PYTHON_FOUND_VERSION"
        return 0
    fi

    log_warn "未找到可用的系统 Python"
    install_uv
    export UV_PYTHON_INSTALL_MIRROR="${UV_PYTHON_INSTALL_MIRROR:-$UV_PYTHON_INSTALL_MIRROR_DEFAULT}"

    log_info "正在通过 uv 安装 Python $PYTHON_VERSION..."
    if $UV_CMD python install "$PYTHON_VERSION"; then
        PYTHON_PATH="$($UV_CMD python find "$PYTHON_VERSION")"
        PYTHON_FOUND_VERSION="$($PYTHON_PATH --version 2>/dev/null)"
        log_success "Python 安装完成：$PYTHON_FOUND_VERSION"
    else
        log_error "安装 Python $PYTHON_VERSION 失败"
        log_info "如果你有自建 R2 / 对象存储镜像，请上传 python-build-standalone 资产并设置："
        log_info "  export UV_PYTHON_INSTALL_MIRROR=$UV_PYTHON_INSTALL_MIRROR_DEFAULT"
        exit 1
    fi
}

check_git() {
    if command -v git >/dev/null 2>&1; then
        return 0
    fi

    log_error "未找到 Git"
    case "$OS" in
        linux)
            case "$DISTRO" in
                ubuntu|debian) log_info "安装 Git：sudo apt update && sudo apt install git" ;;
                fedora)        log_info "安装 Git：sudo dnf install git" ;;
                arch)          log_info "安装 Git：sudo pacman -S git" ;;
                *)             log_info "请使用系统包管理器安装 Git" ;;
            esac
            ;;
        android)
            log_info "安装 Git：pkg install git"
            ;;
        macos)
            log_info "安装 Git：xcode-select --install"
            log_info "或者：brew install git"
            ;;
    esac
    exit 1
}

ensure_git_remote() {
    local remote_name="$1"
    local remote_url="$2"

    [ -n "$remote_name" ] || return 1
    [ -n "$remote_url" ] || return 0

    if git remote get-url "$remote_name" >/dev/null 2>&1; then
        git remote set-url "$remote_name" "$remote_url" >/dev/null 2>&1 || true
    else
        git remote add "$remote_name" "$remote_url" >/dev/null 2>&1 || true
    fi
}

bootstrap_git_repo_from_remote() {
    if ! command -v git >/dev/null 2>&1; then
        return 1
    fi

    local remote_url
    for remote_url in "$@"; do
        [ -n "$remote_url" ] || continue

        if (
            cd "$INSTALL_DIR" &&
            rm -rf .git &&
            git init >/dev/null 2>&1 &&
            ensure_git_remote origin "$remote_url" &&
            git fetch --depth 1 origin "$BRANCH" >/dev/null 2>&1 &&
            git checkout -B "$BRANCH" "origin/$BRANCH" >/dev/null 2>&1
        ); then
            if [ "$remote_url" != "$UPSTREAM_REPO_URL" ]; then
                (
                    cd "$INSTALL_DIR" &&
                    ensure_git_remote upstream "$UPSTREAM_REPO_URL"
                ) || true
            fi
            return 0
        fi
    done

    return 1
}

check_node() {
    log_info "正在检查 Node.js..."

    if command -v node >/dev/null 2>&1; then
        HAS_NODE=true
        log_success "已找到 Node.js（$(node --version)）"
        return 0
    fi

    if [ -x "$HERMES_HOME/node/bin/node" ]; then
        export PATH="$HERMES_HOME/node/bin:$PATH"
        HAS_NODE=true
        log_success "已找到 Node.js（$("$HERMES_HOME/node/bin/node" --version)，Hermes 托管版）"
        return 0
    fi

    install_node
}

install_node() {
    if [ "$DISTRO" = "termux" ]; then
        log_info "正在通过 pkg 安装 Node.js..."
        if pkg install -y nodejs >/dev/null; then
            HAS_NODE=true
            log_success "Node.js 安装完成（$(node --version 2>/dev/null)）"
        else
            HAS_NODE=false
            log_warn "通过 pkg 安装 Node.js 失败"
        fi
        return 0
    fi

    local arch="$(uname -m)"
    local node_arch
    case "$arch" in
        x86_64)        node_arch="x64" ;;
        aarch64|arm64) node_arch="arm64" ;;
        armv7l)        node_arch="armv7l" ;;
        *)
            HAS_NODE=false
            log_warn "当前架构 ($arch) 不支持自动安装 Node.js"
            log_info "如需手动安装，请访问：https://nodejs.org/en/download/"
            return 0
            ;;
    esac

    local node_os
    case "$OS" in
        linux) node_os="linux" ;;
        macos) node_os="darwin" ;;
        *)
            HAS_NODE=false
            log_warn "当前操作系统不支持自动安装 Node.js"
            return 0
            ;;
    esac

    local node_dist_mirror="${NODE_DIST_MIRROR:-$NODE_DIST_MIRROR_DEFAULT}"
    local index_url="${node_dist_mirror}/latest-v${NODE_VERSION}.x/"
    local tarball_name
    tarball_name=$(curl -fsSL "$index_url" | grep -oE "node-v${NODE_VERSION}\.[0-9]+\.[0-9]+-${node_os}-${node_arch}\.tar\.xz" | head -1 || true)
    if [ -z "$tarball_name" ]; then
        tarball_name=$(curl -fsSL "$index_url" | grep -oE "node-v${NODE_VERSION}\.[0-9]+\.[0-9]+-${node_os}-${node_arch}\.tar\.gz" | head -1 || true)
    fi

    if [ -z "$tarball_name" ]; then
        HAS_NODE=false
        log_warn "找不到适用于 $node_os-$node_arch 的 Node.js $NODE_VERSION 二进制包"
        log_info "如需手动安装，请访问：https://nodejs.org/en/download/"
        return 0
    fi

    local tmp_dir download_url extracted_dir installed_ver
    tmp_dir="$(mktemp -d)"
    download_url="${index_url}${tarball_name}"

    log_info "正在下载 $tarball_name..."
    if ! curl -fsSL "$download_url" -o "$tmp_dir/$tarball_name"; then
        rm -rf "$tmp_dir"
        HAS_NODE=false
        log_warn "Node.js 下载失败"
        return 0
    fi

    if [[ "$tarball_name" == *.tar.xz ]]; then
        tar xf "$tmp_dir/$tarball_name" -C "$tmp_dir"
    else
        tar xzf "$tmp_dir/$tarball_name" -C "$tmp_dir"
    fi

    extracted_dir="$(find "$tmp_dir" -maxdepth 1 -type d -name 'node-v*' | head -1)"
    if [ ! -d "$extracted_dir" ]; then
        rm -rf "$tmp_dir"
        HAS_NODE=false
        log_warn "Node.js 解压失败"
        return 0
    fi

    rm -rf "$HERMES_HOME/node"
    mkdir -p "$HERMES_HOME"
    mv "$extracted_dir" "$HERMES_HOME/node"
    rm -rf "$tmp_dir"

    mkdir -p "$HOME/.local/bin"
    ln -sf "$HERMES_HOME/node/bin/node" "$HOME/.local/bin/node"
    ln -sf "$HERMES_HOME/node/bin/npm"  "$HOME/.local/bin/npm"
    ln -sf "$HERMES_HOME/node/bin/npx"  "$HOME/.local/bin/npx"

    export PATH="$HERMES_HOME/node/bin:$PATH"
    installed_ver="$($HERMES_HOME/node/bin/node --version 2>/dev/null)"
    HAS_NODE=true
    log_success "Node.js $installed_ver 已安装到 ~/.hermes/node/"
}

check_optional_system_packages() {
    HAS_RIPGREP=false
    HAS_FFMPEG=false

    if command -v rg >/dev/null 2>&1; then
        HAS_RIPGREP=true
        log_success "已找到 $(rg --version | head -1)"
    else
        log_warn "未找到 ripgrep，将回退为 grep 搜索"
        show_manual_install_hint "ripgrep"
    fi

    if command -v ffmpeg >/dev/null 2>&1; then
        HAS_FFMPEG=true
        log_success "已找到 ffmpeg $(ffmpeg -version 2>/dev/null | head -1 | awk '{print $3}')"
    else
        log_warn "未找到 ffmpeg，语音 / 媒体功能会受限"
        show_manual_install_hint "ffmpeg"
    fi

    if [ "$DISTRO" = "termux" ]; then
        log_info "正在确保 Termux 构建依赖已安装..."
        pkg install -y clang rust make pkg-config libffi openssl >/dev/null || true
    fi
}

# ==========================================================================
# Installation
# ==========================================================================

prepare_repo() {
    log_info "正在准备 Hermes 源码..."

    local tmp_dir tarball extracted_dir marker_file has_git
    tmp_dir="$(mktemp -d)"
    tarball="$tmp_dir/hermes-agent.tar.gz"
    marker_file="$INSTALL_DIR/.hermes-install-source"
    has_git=false

    if command -v git >/dev/null 2>&1; then
        has_git=true
    fi

    if [ -d "$INSTALL_DIR" ] && [ ! -f "$marker_file" ] && [ ! -d "$INSTALL_DIR/.git" ]; then
        log_error "目录已存在，但不是由当前安装器创建：$INSTALL_DIR"
        log_info "请删除该目录，或通过 --dir 指定其他安装位置"
        rm -rf "$tmp_dir"
        exit 1
    fi

    if [ "$has_git" = true ] && [ -n "$GIT_MIRROR_URL" ]; then
        rm -rf "$INSTALL_DIR"
        mkdir -p "$(dirname "$INSTALL_DIR")"
        log_info "正在尝试通过 CNB.cool / Git 镜像克隆：$GIT_MIRROR_URL"
        if git clone --branch "$BRANCH" "$GIT_MIRROR_URL" "$INSTALL_DIR"; then
            cd "$INSTALL_DIR"
            ensure_git_remote upstream "$UPSTREAM_REPO_URL"
            rm -rf "$tmp_dir"
            log_success "源码已就绪（Git 镜像）"
            return 0
        fi
        rm -rf "$INSTALL_DIR"
        log_warn "Git 镜像克隆失败，正在回退到源码包..."
    fi

    local tarball_urls=()
    while IFS= read -r url; do
        tarball_urls+=("$url")
    done < <(get_source_tarball_urls)

    if download_to_file "$tarball" "${tarball_urls[@]}"; then
        rm -rf "$INSTALL_DIR"
        mkdir -p "$(dirname "$INSTALL_DIR")"
        tar -xzf "$tarball" -C "$tmp_dir"
        extracted_dir="$(find "$tmp_dir" -mindepth 1 -maxdepth 1 -type d | head -1)"
        if [ -z "$extracted_dir" ] || [ ! -d "$extracted_dir" ]; then
            rm -rf "$tmp_dir"
            log_error "解压 Hermes 源码包失败"
            exit 1
        fi
        mv "$extracted_dir" "$INSTALL_DIR"

        if [ "$has_git" = true ] && bootstrap_git_repo_from_remote "$GIT_MIRROR_URL" "$UPSTREAM_REPO_URL"; then
            printf 'tarball+git\n' > "$marker_file"
            log_success "源码已就绪（源码包安装，已补全 Git 元数据，可直接使用 hermes update）"
        else
            printf 'tarball\n' > "$marker_file"
            if [ "$has_git" = true ]; then
                log_warn "源码已就绪（源码包安装），但 Git 元数据初始化失败；后续 hermes update 可能不可用"
            else
                log_warn "当前系统未安装 Git，本次使用源码包安装；如需后续执行 hermes update，请先安装 Git 后重新运行安装脚本"
            fi
        fi

        rm -rf "$tmp_dir"
        cd "$INSTALL_DIR"
        return 0
    fi

    rm -rf "$tmp_dir"
    log_warn "源码包下载失败，正在回退到 git clone"
    check_git
    rm -rf "$INSTALL_DIR"

    if [ -n "$GIT_MIRROR_URL" ]; then
        log_info "正在尝试 Git 镜像：$GIT_MIRROR_URL"
        if git clone --branch "$BRANCH" "$GIT_MIRROR_URL" "$INSTALL_DIR"; then
            cd "$INSTALL_DIR"
            log_success "源码已就绪（Git 镜像）"
            return 0
        fi
        rm -rf "$INSTALL_DIR"
    fi

    log_info "正在尝试上游 GitHub 仓库..."
    if git clone --branch "$BRANCH" "$UPSTREAM_REPO_URL" "$INSTALL_DIR"; then
        cd "$INSTALL_DIR"
        log_success "源码已就绪（GitHub 克隆）"
        return 0
    fi

    log_error "获取 Hermes 源码失败"
    exit 1
}

patch_hermes_setup_launch_behavior() {
    local setup_py="$INSTALL_DIR/hermes_cli/setup.py"
    [ -f "$setup_py" ] || return 0

    if grep -q "HERMES_SKIP_AUTO_LAUNCH_CHAT" "$setup_py"; then
        return 0
    fi

    "$PYTHON_PATH" - "$setup_py" <<'PY'
from pathlib import Path
import sys

path = Path(sys.argv[1])
text = path.read_text(encoding="utf-8")
import_block = '''from hermes_cli.cli_output import (  # noqa: E402
    print_error,
    print_info,
    print_success,
    print_warning,
)
'''

translation_block = '''from hermes_cli.cli_output import (  # noqa: E402
    print_error,
    print_info,
    print_success,
    print_warning,
)

_SETUP_TRANSLATIONS = [
    ("Hermes Setup — Non-interactive mode", "Hermes 配置向导 —— 非交互模式"),
    ("The interactive wizard cannot be used here.", "当前环境无法使用交互式配置向导。"),
    ("Configure Hermes using environment variables or config commands:", "你可以通过环境变量或配置命令来设置 Hermes："),
    ("Or set OPENROUTER_API_KEY / OPENAI_API_KEY in your environment.", "或者在环境变量中设置 OPENROUTER_API_KEY / OPENAI_API_KEY。"),
    ("Run 'hermes setup' in an interactive terminal to use the full wizard.", "如需完整向导，请在交互式终端中运行：hermes setup"),
    ("  Skipped (keeping current)", "  已跳过（保留当前设置）"),
    ("  Enter for default", "  直接回车使用默认项"),
    ("Ctrl+C to exit", "Ctrl+C 退出"),
    ("  Select [", "  请选择 ["),
    ("Please enter a number between", "请输入一个数字，范围："),
    ("Please enter a number", "请输入数字"),
    ("Please enter 'y' or 'n'", "请输入 y 或 n"),
    ("Launch hermes chat now?", "现在立即启动 hermes 聊天吗？"),
    ("Connect a messaging platform? (Telegram, Discord, etc.)", "现在连接消息平台吗？（Telegram、Discord 等）"),
    ("Set up messaging now (recommended)", "现在配置消息平台（推荐）"),
    ("Skip — set up later with 'hermes setup gateway'", "先跳过，之后可通过 'hermes setup gateway' 配置"),
]

def _translate_setup_text(text: str) -> str:
    if not isinstance(text, str):
        return text
    translated = text
    for old, new in _SETUP_TRANSLATIONS:
        translated = translated.replace(old, new)
    return translated

_orig_print_error = print_error
_orig_print_info = print_info
_orig_print_success = print_success
_orig_print_warning = print_warning

def print_error(message):
    _orig_print_error(_translate_setup_text(message))

def print_info(message):
    _orig_print_info(_translate_setup_text(message))

def print_success(message):
    _orig_print_success(_translate_setup_text(message))

def print_warning(message):
    _orig_print_warning(_translate_setup_text(message))
'''

if "_translate_setup_text(" not in text and import_block in text:
    text = text.replace(import_block, translation_block, 1)

replacements = [
    (
        '''def print_noninteractive_setup_guidance(reason: str | None = None) -> None:
    """Print guidance for headless/non-interactive setup flows."""
    print()
    print(color("⚕ Hermes Setup — Non-interactive mode", Colors.CYAN, Colors.BOLD))
    print()
    if reason:
        print_info(reason)
    print_info("The interactive wizard cannot be used here.")
    print()
    print_info("Configure Hermes using environment variables or config commands:")
    print_info("  hermes config set model.provider custom")
    print_info("  hermes config set model.base_url http://localhost:8080/v1")
    print_info("  hermes config set model.default your-model-name")
    print()
    print_info("Or set OPENROUTER_API_KEY / OPENAI_API_KEY in your environment.")
    print_info("Run 'hermes setup' in an interactive terminal to use the full wizard.")
    print()
''',
        '''def print_noninteractive_setup_guidance(reason: str | None = None) -> None:
    """Print guidance for headless/non-interactive setup flows."""
    print()
    print(color("⚕ Hermes 配置向导 —— 非交互模式", Colors.CYAN, Colors.BOLD))
    print()
    if reason:
        print_info(reason)
    print_info("当前环境无法使用交互式配置向导。")
    print()
    print_info("你可以通过环境变量或配置命令来设置 Hermes：")
    print_info("  hermes config set model.provider custom")
    print_info("  hermes config set model.base_url http://localhost:8080/v1")
    print_info("  hermes config set model.default your-model-name")
    print()
    print_info("或者在环境变量中设置 OPENROUTER_API_KEY / OPENAI_API_KEY。")
    print_info("如需完整向导，请在交互式终端中运行：hermes setup")
    print()
'''
    ),
    (
        '''def prompt(question: str, default: str = None, password: bool = False) -> str:
    """Prompt for input with optional default."""
    if default:
        display = f"{question} [{default}]: "
    else:
        display = f"{question}: "
''',
        '''def prompt(question: str, default: str = None, password: bool = False) -> str:
    """Prompt for input with optional default."""
    question = _translate_setup_text(question)
    if default:
        display = f"{question} [{default}]: "
    else:
        display = f"{question}: "
'''
    ),
    (
        '''def prompt_choice(question: str, choices: list, default: int = 0) -> int:
    """Prompt for a choice from a list with arrow key navigation.

    Escape keeps the current default (skips the question).
    Ctrl+C exits the wizard.
    """
    idx = _curses_prompt_choice(question, choices, default)
''',
        '''def prompt_choice(question: str, choices: list, default: int = 0) -> int:
    """Prompt for a choice from a list with arrow key navigation.

    Escape keeps the current default (skips the question).
    Ctrl+C exits the wizard.
    """
    question = _translate_setup_text(question)
    choices = [_translate_setup_text(str(choice)) for choice in choices]
    idx = _curses_prompt_choice(question, choices, default)
'''
    ),
    (
        '''def prompt_yes_no(question: str, default: bool = True) -> bool:
    """Prompt for yes/no. Ctrl+C exits, empty input returns default."""
    default_str = "Y/n" if default else "y/N"
''',
        '''def prompt_yes_no(question: str, default: bool = True) -> bool:
    """Prompt for yes/no. Ctrl+C exits, empty input returns default."""
    question = _translate_setup_text(question)
    default_str = "Y/n（回车默认是）" if default else "y/N（回车默认否）"
'''
    ),
    (
        '''        if value in ("y", "yes"):
            return True
        if value in ("n", "no"):
            return False
        print_error("Please enter 'y' or 'n'")
''',
        '''        if value in ("y", "yes", "是"):
            return True
        if value in ("n", "no", "否"):
            return False
        print_error("请输入 y 或 n")
'''
    ),
    (
        '''def _offer_launch_chat():
    """Prompt the user to jump straight into chat after setup."""
    print()
''',
        '''def _offer_launch_chat():
    """Prompt the user to jump straight into chat after setup."""
    if os.environ.get("HERMES_SKIP_AUTO_LAUNCH_CHAT") == "1":
        print_info("镜像安装器将跳过自动启动聊天。准备好后请在新终端中运行：hermes")
        return

    print()
'''
    ),
]

for old, new in replacements:
    if old in text:
        text = text.replace(old, new, 1)

path.write_text(text, encoding="utf-8")
PY

    log_success "已修补 Hermes 配置向导：镜像安装时跳过自动启动聊天"
}

setup_venv() {
    if [ "$USE_VENV" = false ]; then
        log_info "跳过虚拟环境创建（--no-venv）"
        return 0
    fi

    log_info "正在创建虚拟环境..."
    rm -rf "$INSTALL_DIR/venv"

    local venv_log
    venv_log="$(mktemp)"

    if "$PYTHON_PATH" -m venv "$INSTALL_DIR/venv" >"$venv_log" 2>&1; then
        log_success "虚拟环境已就绪（$("$INSTALL_DIR/venv/bin/python" --version 2>/dev/null)）"
        rm -f "$venv_log"
        return 0
    fi

    if ensure_python_venv_package; then
        log_info "已补齐系统 venv 组件，正在重新创建虚拟环境..."
        if "$PYTHON_PATH" -m venv "$INSTALL_DIR/venv" >"$venv_log" 2>&1; then
            log_success "虚拟环境已就绪（$("$INSTALL_DIR/venv/bin/python" --version 2>/dev/null)）"
            rm -f "$venv_log"
            return 0
        fi
        log_warn "系统 venv 组件已安装，但仍无法使用系统 Python 创建虚拟环境"
    fi

    if [ "$DISTRO" != "termux" ]; then
        log_warn "系统 Python 无法创建虚拟环境（Ubuntu / Debian 常见原因是缺少 python3-venv）"
        install_uv
        export UV_PYTHON_INSTALL_MIRROR="${UV_PYTHON_INSTALL_MIRROR:-$UV_PYTHON_INSTALL_MIRROR_DEFAULT}"

        if $UV_CMD venv "$INSTALL_DIR/venv" --python "$PYTHON_PATH" >/tmp/hermes-uv-venv.log 2>&1; then
            log_success "虚拟环境已就绪（$("$INSTALL_DIR/venv/bin/python" --version 2>/dev/null)）"
            return 0
        fi

        log_warn "uv 无法复用系统 Python，正在尝试托管版 Python $PYTHON_VERSION..."
        if $UV_CMD venv "$INSTALL_DIR/venv" --python "$PYTHON_VERSION" >/tmp/hermes-uv-venv.log 2>&1; then
            log_success "虚拟环境已就绪（$("$INSTALL_DIR/venv/bin/python" --version 2>/dev/null)）"
            rm -f "$venv_log"
            return 0
        fi

        if [ -f /tmp/hermes-uv-venv.log ]; then
            log_warn "uv 创建虚拟环境失败，关键输出如下："
            tail -20 /tmp/hermes-uv-venv.log | while IFS= read -r line; do
                log_warn "  $line"
            done
        fi
    fi

    log_error "创建虚拟环境失败"
    if [ -s "$venv_log" ]; then
        log_warn "系统 Python 创建虚拟环境失败，关键输出如下："
        tail -20 "$venv_log" | while IFS= read -r line; do
            log_warn "  $line"
        done
    fi
    rm -f "$venv_log"
    if [ "$DISTRO" = "ubuntu" ] || [ "$DISTRO" = "debian" ]; then
        log_info "你可能需要执行：sudo apt install python3-venv"
        log_info "或者安装对应版本的软件包，例如：sudo apt install python3.12-venv"
    fi
    exit 1
}

install_deps() {
    log_info "正在安装 Python 依赖..."

    local pip_python
    if [ "$USE_VENV" = true ]; then
        pip_python="$INSTALL_DIR/venv/bin/python"
    else
        pip_python="$PYTHON_PATH"
    fi

    if [ "$DISTRO" = "termux" ]; then
        if [ -z "${ANDROID_API_LEVEL:-}" ]; then
            ANDROID_API_LEVEL="$(getprop ro.build.version.sdk 2>/dev/null || true)"
            [ -z "$ANDROID_API_LEVEL" ] && ANDROID_API_LEVEL=24
            export ANDROID_API_LEVEL
            log_info "正在使用 ANDROID_API_LEVEL=$ANDROID_API_LEVEL 构建 Android wheel"
        fi

        if ! pip_install_with_fallback "$pip_python" install --upgrade pip setuptools wheel; then
            log_error "升级 pip / setuptools / wheel 失败"
            exit 1
        fi
        if ! pip_install_with_fallback "$pip_python" install -e '.[termux]' -c constraints-termux.txt; then
            log_warn "Termux 扩展安装（.[termux]）失败，正在回退到基础安装..."
            if ! pip_install_with_fallback "$pip_python" install -e '.' -c constraints-termux.txt; then
                log_error "Termux 环境下安装 Python 包失败"
                log_info "请确认已安装这些依赖：pkg install clang rust make pkg-config libffi openssl"
                exit 1
            fi
        fi
        log_success "Python 依赖安装完成"
        return 0
    fi

    if ! pip_install_with_fallback "$pip_python" install --upgrade pip setuptools wheel; then
        log_warn "升级 pip / setuptools / wheel 失败，继续尝试直接安装 Hermes 依赖"
    fi

    if [ "$DISTRO" = "ubuntu" ] || [ "$DISTRO" = "debian" ]; then
        local need_build_tools=false
        for pkg in gcc python3-dev libffi-dev; do
            if ! dpkg -s "$pkg" >/dev/null 2>&1; then
                need_build_tools=true
                break
            fi
        done
        if [ "$need_build_tools" = true ]; then
            log_warn "部分 Python 包可能需要编译工具（gcc/python3-dev/libffi-dev）"
            log_info "如果安装失败，请执行：sudo apt install build-essential python3-dev libffi-dev"
        fi
    fi

    if [ "$INSTALL_OPTIONAL_EXTRAS" = true ]; then
        log_info "已启用 --with-optional-extras，正在安装完整 Python 扩展依赖（可能需要较长时间）..."
        if ! pip_install_with_fallback "$pip_python" install -e '.[all]'; then
            log_warn "完整安装（.[all]）失败，正在回退到基础安装..."
            if ! pip_install_with_fallback "$pip_python" install -e '.'; then
                log_error "安装 Python 包失败"
                log_info "当前使用的 PyPI 镜像：$PIP_INDEX_URL"
                exit 1
            fi
        fi
    else
        log_info "为提高安装速度与成功率，默认只安装 Hermes 核心依赖。"
        log_info "浏览器、RL 训练等体积较大 / 不常用扩展默认跳过；如有需要可稍后手动补装。"
        if ! pip_install_with_fallback "$pip_python" install -e '.'; then
            log_error "安装 Python 包失败"
            log_info "当前使用的 PyPI 镜像：$PIP_INDEX_URL"
            exit 1
        fi
    fi

    log_success "Python 依赖安装完成"
}

install_agent_browser_binary() {
    local asset_name dest_dir dest
    case "$OS-$(uname -m)" in
        linux-x86_64)        asset_name="agent-browser-linux-x64" ;;
        linux-aarch64|linux-arm64) asset_name="agent-browser-linux-arm64" ;;
        macos-x86_64)        asset_name="agent-browser-darwin-x64" ;;
        macos-arm64)         asset_name="agent-browser-darwin-arm64" ;;
        *)
            log_warn "当前平台 $(uname -s)-$(uname -m) 没有配置镜像版 agent-browser 二进制文件"
            return 1
            ;;
    esac

    dest_dir="$INSTALL_DIR/node_modules/agent-browser/bin"
    dest="$dest_dir/$asset_name"
    mkdir -p "$dest_dir"

    if download_to_file \
        "$dest" \
        "$MIRROR_BASE_URL/third-party/agent-browser/releases/download/v${AGENT_BROWSER_VERSION}/${asset_name}" \
        "https://github.com/vercel-labs/agent-browser/releases/download/v${AGENT_BROWSER_VERSION}/${asset_name}"; then
        chmod +x "$dest" 2>/dev/null || true
        log_success "agent-browser 原生二进制已就绪（$asset_name）"
        return 0
    fi

    log_warn "获取 agent-browser 原生二进制失败"
    return 1
}

install_optional_node_components() {
    if [ "$INSTALL_NODE_RUNTIME" = false ] && [ "$INSTALL_BROWSER_TOOLS" = false ] && [ "$INSTALL_WHATSAPP_BRIDGE" = false ]; then
        log_info "默认跳过可选的 Node.js 组件"
        return 0
    fi

    check_node
    if [ "$HAS_NODE" != true ]; then
        return 0
    fi

    if [ "$INSTALL_BROWSER_TOOLS" = true ]; then
        if [ -f "$INSTALL_DIR/package.json" ]; then
            log_info "正在安装浏览器相关 JS 依赖（尽力而为）..."
            (
                cd "$INSTALL_DIR"
                npm install --silent --ignore-scripts
            ) || log_warn "npm install 失败（浏览器工具未安装）"

            install_agent_browser_binary || true

            if [ -n "$PLAYWRIGHT_DOWNLOAD_HOST_CONFIG" ]; then
                log_info "正在从配置好的镜像安装 Playwright Chromium..."
                (
                    cd "$INSTALL_DIR"
                    PLAYWRIGHT_DOWNLOAD_HOST="$PLAYWRIGHT_DOWNLOAD_HOST_CONFIG" npx playwright install chromium
                ) || log_warn "Playwright Chromium 下载失败"
            else
                log_warn "默认跳过 Playwright 浏览器下载"
                log_info "如果后续需要浏览器工具，请先把 Playwright 资源上传到你的 R2 / 对象存储镜像，然后执行："
                log_info "  cd $INSTALL_DIR && PLAYWRIGHT_DOWNLOAD_HOST=<你的镜像地址> npx playwright install chromium"
            fi
        fi
    fi

    if [ "$INSTALL_WHATSAPP_BRIDGE" = true ]; then
        log_warn "中国大陆镜像版默认跳过 WhatsApp 桥接自动安装"
        log_info "原因：上游依赖固定绑定到了 GitHub git URL"
        log_info "如果你后续把 Baileys / libsignal 镜像到了 Gitee 或你的对象存储镜像，可再到这里手动安装："
        log_info "  $INSTALL_DIR/scripts/whatsapp-bridge"
    fi
}

setup_path() {
    log_info "正在设置 hermes 命令..."

    if [ "$USE_VENV" = true ]; then
        HERMES_BIN="$INSTALL_DIR/venv/bin/hermes"
    else
        HERMES_BIN="$(command -v hermes 2>/dev/null || true)"
        if [ -z "$HERMES_BIN" ]; then
            log_warn "安装后在 PATH 中找不到 hermes"
            return 0
        fi
    fi

    if [ ! -x "$HERMES_BIN" ]; then
        log_warn "在 $HERMES_BIN 找不到 hermes 入口文件"
        return 0
    fi

    local command_link_dir command_link_display_dir
    command_link_dir="$(get_command_link_dir)"
    command_link_display_dir="$(get_command_link_display_dir)"

    mkdir -p "$command_link_dir"
    ln -sf "$HERMES_BIN" "$command_link_dir/hermes"
    log_success "已创建命令链接 hermes → $command_link_display_dir/hermes"

    if [ "$DISTRO" = "termux" ]; then
        export PATH="$command_link_dir:$PATH"
        log_success "hermes 命令已就绪"
        return 0
    fi

    if ! echo "$PATH" | tr ':' '\n' | grep -q "^$command_link_dir$"; then
        local shell_configs=() login_shell path_line shell_config
        login_shell="$(basename "${SHELL:-/bin/bash}")"
        case "$login_shell" in
            zsh)
                [ -f "$HOME/.zshrc" ] && shell_configs+=("$HOME/.zshrc")
                [ -f "$HOME/.zprofile" ] && shell_configs+=("$HOME/.zprofile")
                if [ ${#shell_configs[@]} -eq 0 ]; then
                    touch "$HOME/.zshrc"
                    shell_configs+=("$HOME/.zshrc")
                fi
                ;;
            bash)
                [ -f "$HOME/.bashrc" ] && shell_configs+=("$HOME/.bashrc")
                [ -f "$HOME/.bash_profile" ] && shell_configs+=("$HOME/.bash_profile")
                ;;
            *)
                [ -f "$HOME/.bashrc" ] && shell_configs+=("$HOME/.bashrc")
                [ -f "$HOME/.zshrc" ] && shell_configs+=("$HOME/.zshrc")
                ;;
        esac
        [ -f "$HOME/.profile" ] && shell_configs+=("$HOME/.profile")

        path_line='export PATH="$HOME/.local/bin:$PATH"'
        for shell_config in "${shell_configs[@]}"; do
            if ! grep -v '^[[:space:]]*#' "$shell_config" 2>/dev/null | grep -qE 'PATH=.*\.local/bin'; then
                {
                    echo ""
                    echo "# Hermes Agent —— 确保 ~/.local/bin 在 PATH 中"
                    echo "$path_line"
                } >> "$shell_config"
                log_success "已在 $shell_config 中加入 ~/.local/bin"
            fi
        done

        if [ ${#shell_configs[@]} -eq 0 ]; then
            log_warn "无法自动识别 shell 配置文件来写入 ~/.local/bin"
            log_info "请手动添加：$path_line"
        fi
    else
        log_info "~/.local/bin 已在 PATH 中"
    fi

    export PATH="$command_link_dir:$PATH"
    log_success "hermes 命令已就绪"
}

copy_config_templates() {
    log_info "正在设置配置文件..."

    mkdir -p "$HERMES_HOME"/{cron,sessions,logs,pairing,hooks,image_cache,audio_cache,memories,skills,whatsapp/session}

    if [ ! -f "$HERMES_HOME/.env" ]; then
        if [ -f "$INSTALL_DIR/.env.example" ]; then
            cp "$INSTALL_DIR/.env.example" "$HERMES_HOME/.env"
        else
            touch "$HERMES_HOME/.env"
        fi
        log_success "已创建 ~/.hermes/.env"
    else
        log_info "~/.hermes/.env 已存在，保留现有内容"
    fi

    if [ ! -f "$HERMES_HOME/config.yaml" ] && [ -f "$INSTALL_DIR/cli-config.yaml.example" ]; then
        cp "$INSTALL_DIR/cli-config.yaml.example" "$HERMES_HOME/config.yaml"
        log_success "已根据模板创建 ~/.hermes/config.yaml"
    elif [ -f "$HERMES_HOME/config.yaml" ]; then
        log_info "~/.hermes/config.yaml 已存在，保留现有内容"
    fi

    if [ ! -f "$HERMES_HOME/SOUL.md" ]; then
        cat > "$HERMES_HOME/SOUL.md" << 'SOUL_EOF'
# Hermes Agent Persona

<!--
Edit this file to customize Hermes's personality and tone.
This file is loaded fresh on every message.
-->
SOUL_EOF
        log_success "已创建 ~/.hermes/SOUL.md"
    fi

    local sync_python
    if [ "$USE_VENV" = true ] && [ -x "$INSTALL_DIR/venv/bin/python" ]; then
        sync_python="$INSTALL_DIR/venv/bin/python"
    else
        sync_python="$PYTHON_PATH"
    fi

    if [ -f "$INSTALL_DIR/tools/skills_sync.py" ]; then
        if "$sync_python" "$INSTALL_DIR/tools/skills_sync.py" 2>/dev/null; then
            log_success "已同步技能到 ~/.hermes/skills/"
        elif [ -d "$INSTALL_DIR/skills" ]; then
            cp -r "$INSTALL_DIR/skills/"* "$HERMES_HOME/skills/" 2>/dev/null || true
            log_success "已复制技能到 ~/.hermes/skills/"
        fi
    elif [ -d "$INSTALL_DIR/skills" ]; then
        cp -r "$INSTALL_DIR/skills/"* "$HERMES_HOME/skills/" 2>/dev/null || true
        log_success "已复制技能到 ~/.hermes/skills/"
    fi
}

run_setup_wizard() {
    if [ "$RUN_SETUP" = false ]; then
        log_info "跳过配置向导（--skip-setup）"
        return 0
    fi

    if ! [ -e /dev/tty ]; then
        log_info "没有可用终端，已跳过配置向导。你可以稍后手动运行：hermes setup"
        return 0
    fi

    echo ""
    log_success "Hermes Agent 核心安装已经完成，接下来进入配置 Hermes Agent 环节。"
    log_info "镜像站: https://hermes.ver0.cn"
    log_info "社区教程: https://hermesagent.org.cn/docs/getting-started/setup-wizard"
    echo ""
    log_info "正在启动配置向导..."
    echo ""

    local setup_log setup_status
    setup_log="$(mktemp)"

    cd "$INSTALL_DIR"
    if [ "$USE_VENV" = true ]; then
        HERMES_SKIP_AUTO_LAUNCH_CHAT=1 "$INSTALL_DIR/venv/bin/python" -m hermes_cli.main setup < /dev/tty 2>&1 | tee "$setup_log"
        setup_status=${PIPESTATUS[0]}
    else
        HERMES_SKIP_AUTO_LAUNCH_CHAT=1 "$PYTHON_PATH" -m hermes_cli.main setup < /dev/tty 2>&1 | tee "$setup_log"
        setup_status=${PIPESTATUS[0]}
    fi

    if [ "$setup_status" -ne 0 ]; then
        if grep -q "Launch hermes chat now?" "$setup_log" && grep -q "prompt_toolkit" "$setup_log" && grep -q "Invalid argument" "$setup_log"; then
            log_warn "检测到已知的 TTY 问题：在 curl | bash 场景下自动启动 Hermes 聊天会失败。"
            log_info "安装和配置其实已经完成。请打开一个新终端后运行：hermes"
            rm -f "$setup_log"
            return 0
        fi

        log_error "配置向导执行失败"
        log_info "你可以稍后重新执行：hermes setup"
        rm -f "$setup_log"
        return 1
    fi

    rm -f "$setup_log"
}

maybe_start_gateway() {
    local env_file="$HERMES_HOME/.env"
    [ -f "$env_file" ] || return 0

    local has_messaging=false
    local var val
    for var in TELEGRAM_BOT_TOKEN DISCORD_BOT_TOKEN SLACK_BOT_TOKEN SLACK_APP_TOKEN WHATSAPP_ENABLED; do
        val="$(grep "^${var}=" "$env_file" 2>/dev/null | cut -d'=' -f2-)"
        if [ -n "$val" ] && [ "$val" != "your-token-here" ]; then
            has_messaging=true
            break
        fi
    done

    [ "$has_messaging" = true ] || return 0
    [ -e /dev/tty ] || return 0

    echo ""
    log_info "检测到消息平台 Token"
    log_info "Hermes 要正常收发消息，需要启动网关进程"
    echo ""

    read -p "安装结束后要立即启动网关吗？[Y/n] " -n 1 -r < /dev/tty
    echo
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        log_info "已跳过。后续可手动运行：hermes gateway"
        return 0
    fi

    local hermes_cmd
    hermes_cmd="$(get_hermes_command_path)"

    if [ "$DISTRO" != "termux" ] && command -v systemctl >/dev/null 2>&1; then
        if $hermes_cmd gateway install 2>/dev/null; then
            if $hermes_cmd gateway start 2>/dev/null; then
                log_success "网关已启动"
            else
                log_warn "网关服务已安装，但启动失败"
            fi
        else
            log_warn "Systemd 安装失败，请手动运行：hermes gateway"
        fi
    else
        nohup $hermes_cmd gateway > "$HERMES_HOME/logs/gateway.log" 2>&1 &
        log_success "网关已启动 in background (logs: ~/.hermes/logs/gateway.log)"
    fi
}

print_success() {
    echo ""
    echo -e "${GREEN}${BOLD}"
    echo "┌─────────────────────────────────────────────────────────┐"
    echo "│              ✓ 安装完成！                   │"
    echo "└─────────────────────────────────────────────────────────┘"
    echo -e "${NC}"
    echo ""

    echo -e "${CYAN}${BOLD}📁 你的文件（都在 ~/.hermes/ 下）：${NC}"
    echo ""
    echo -e "   ${YELLOW}配置：${NC}    ~/.hermes/config.yaml"
    echo -e "   ${YELLOW}密钥：${NC}  ~/.hermes/.env"
    echo -e "   ${YELLOW}数据：${NC}      ~/.hermes/cron/, sessions/, logs/"
    echo -e "   ${YELLOW}代码：${NC}      ~/.hermes/hermes-agent/"
    echo ""

    echo -e "${CYAN}─────────────────────────────────────────────────────────${NC}"
    echo ""
    echo -e "${CYAN}${BOLD}🚀 常用命令：${NC}"
    echo ""
    echo -e "   ${GREEN}hermes${NC}              开始聊天"
    echo -e "   ${GREEN}hermes setup${NC}        配置 API Key 和设置"
    echo -e "   ${GREEN}hermes config${NC}       查看 / 编辑配置"
    echo -e "   ${GREEN}hermes gateway install${NC} 安装网关服务"
    echo -e ""

    if [ "$INSTALL_BROWSER_TOOLS" = false ]; then
        echo -e "${YELLOW}⚡ 中国大陆镜像版默认跳过 Browser / Chromium 工具链。${NC}"
        echo -e "${YELLOW}   如果你后续需要浏览器功能，请先镜像浏览器资源后再使用 --with-browser 重装。${NC}"
        echo ""
    fi

    if [ "$INSTALL_WHATSAPP_BRIDGE" = false ]; then
        echo -e "${YELLOW}⚡ WhatsApp 桥接未自动安装（上游依赖仍绑定 GitHub git 源）。${NC}"
        echo ""
    fi

    if [ "$INSTALL_OPTIONAL_EXTRAS" = false ]; then
        echo -e "${YELLOW}⚡ 当前默认只安装 Hermes 核心 Python 依赖。${NC}"
        echo -e "${YELLOW}   如需完整扩展依赖，可稍后在仓库目录中执行：${NC}"
        echo "   ./venv/bin/python -m pip install -e '.[all]'"
        echo ""
    fi

    if [ "$DISTRO" = "termux" ]; then
        echo -e "${YELLOW}⚡ 'hermes' 已链接到 $(get_command_link_display_dir)，Termux 下可直接使用。${NC}"
    else
        echo -e "${YELLOW}⚡ 请重新加载 shell 后再使用 'hermes' 命令：${NC}"
        LOGIN_SHELL="$(basename "${SHELL:-/bin/bash}")"
        if [ "$LOGIN_SHELL" = "zsh" ]; then
            echo "   source ~/.zshrc"
        elif [ "$LOGIN_SHELL" = "bash" ]; then
            echo "   source ~/.bashrc"
        else
            echo "   source ~/.bashrc   # 或 ~/.zshrc"
        fi
    fi
    echo ""
}

# ==========================================================================
# Main
# ==========================================================================

main() {
    print_banner
    configure_network_defaults

    print_step "第 1 步 / 7：识别系统环境"
    detect_os

    print_step "第 2 步 / 7：准备 Python 运行环境"
    check_python

    print_step "第 3 步 / 7：检查基础工具"
    check_optional_system_packages

    print_step "第 4 步 / 7：获取 Hermes 代码"
    prepare_repo
    patch_hermes_setup_launch_behavior

    print_step "第 5 步 / 7：创建独立运行环境"
    setup_venv

    print_step "第 6 步 / 7：安装 Hermes 核心依赖"
    install_deps

    print_step "第 7 步 / 7：写入命令与配置文件"
    install_optional_node_components
    setup_path
    copy_config_templates
    run_setup_wizard
    maybe_start_gateway
    print_success
}

main
