#!/usr/bin/env bash
# ============================================================================
#  LVX (XRuntime) 1.0.0 -- Linux x86_64 安装脚本 / installer
# ----------------------------------------------------------------------------
#  用法 / usage:
#    curl -fsSL https://lvx-office.com/install.sh | bash              # 单条命令安装（自动下载 + 校验 + 安装）
#    curl -fsSL https://lvx-office.com/install.sh | sudo bash -s -- --system    # 系统级（/usr/local）
#    curl -fsSL https://lvx-office.com/install.sh | bash -s -- --flutter-extras # 另装 Flutter/Dart 运行时扩展包
#    curl -fsSL https://lvx-office.com/install.sh | bash -s -- --uninstall      # 卸载
#    ./install.sh                     装到用户目录：~/.local/lib/lvx + ~/.local/bin（免 sudo）
#    sudo ./install.sh --system       装到系统目录：/usr/local（全机可用）
#    ./install.sh --prefix /opt/lvx --bin-dir /opt/lvx/bin
#    ./install.sh --uninstall         卸载（按 $PREFIX/installed-files.txt）
#    ./install.sh --tar lvx-1.0.0-linux-x86_64.tar.gz   直接解包安装（离线可用）
#
#  选项 / options:
#    --prefix DIR     安装前缀（默认 $HOME/.local/lib/lvx；--system 时 /usr/local）
#    --bin-dir DIR    命令链接目录（默认 $HOME/.local/bin；--system 时 /usr/local/bin）
#    --system         等价于 --prefix /usr/local --bin-dir /usr/local/bin
#    --tar FILE       从压缩包安装（脚本与 tar.gz 放在一起时自动查找）
#    --url URL        从指定地址下载核心包（默认 <base-url>/lvx-<版本>-linux-<架构>.tar.gz）
#    --base-url URL   下载基址（也可用环境变量 LVX_BASE_URL；默认 https://lvx-office.com/lvx/<版本>）
#    --flutter-extras 额外安装 Flutter/Dart 运行时扩展包（约 63 MiB）
#    --no-verify      跳过 sha256 校验（默认会用同基址的 SHA256SUMS 校验）
#    --no-agent       不装 lvx-agent（网页商店代理）
#    --no-dartrun     不装 lvx_dartrun（Flutter/Dart 运行时宿主）
#    --no-plugins     不装随包的官方插件（.so）
#    --force-plugins  覆盖插件目录里已有的同名 .so
#    --add-path       把命令目录写进 ~/.bashrc（带标记，可重复执行）
#    --force-agent-bin  覆盖 ~/.lvx/bin 里已有的 CLI 指向
#    --uninstall      卸载
#    -h | --help      帮助
#
#  装完的布局 / layout:
#    $PREFIX/bin/lvx lvx-agent lvx_lvxc lvx_dartrun
#    $PREFIX/bin/plugins/            ← 就近插件目录（丢 .so 进来即生效）
#    $PREFIX/share/apps/store.lvx    ← 示例 LVXB 商店
#    $PREFIX/share/doc/lvx/*.md      ← 文档
#    ~/.lvx/bin                      ← 一行文本：lvx-agent 该驱动哪个 CLI
#                                      （~/.lvx 是数据/配置目录：插件、软件源、缓存）
# ============================================================================
set -euo pipefail

APP=lvx
VERSION="1.0.0"
case "$(uname -m)" in
  amd64|x86_64)   ARCH="x86_64" ;;
  aarch64|arm64)  ARCH="aarch64" ;;
  *)              ARCH="$(uname -m)" ;;
esac
# 以 curl | bash 方式运行时 BASH_SOURCE 不是真实文件：SELF_DIR 留空，走下载路径
SELF_DIR=""
if [ -n "${BASH_SOURCE[0]:-}" ] && [ -f "${BASH_SOURCE[0]}" ]; then
  SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
fi

PREFIX="${HOME}/.local/lib/lvx"
BIN_DIR="${HOME}/.local/bin"
SYSTEM=0
WITH_AGENT=1
WITH_DARTRUN=1
WITH_PLUGINS=1
FORCE_PLUGINS=0
ADD_PATH=0
FORCE_AGENT_BIN=0
UNINSTALL=0
TARBALL=""
TARBALL_URL=""
FLUTTER_URL=""
BASE_URL="${LVX_BASE_URL:-https://lvx-office.com/lvx/$VERSION}"
WITH_FLUTTER=0
VERIFY=1
DOWNLOAD_DIR=""

die()  { printf '\033[31m错误:\033[0m %s\n' "$*" >&2; exit 1; }
http_get() { # http_get <url> <out-file>
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL --retry 2 -o "$2" "$1"
  elif command -v wget >/dev/null 2>&1; then
    wget -q -O "$2" "$1"
  else
    die "自动下载需要 curl 或 wget；也可以手动下载压缩包后用 --tar 指定"
  fi
}
verify_sha256() { # verify_sha256 <file> <file-name>
  [ "$VERIFY" = 1 ] || { warn "已跳过校验（--no-verify）"; return 0; }
  local sums="$DOWNLOAD_DIR/SHA256SUMS" want got
  if [ ! -s "$sums" ] && ! http_get "$BASE_URL/SHA256SUMS?v=$VERSION" "$sums" 2>/dev/null; then
    warn "拿不到 $BASE_URL/SHA256SUMS，跳过校验"
    return 0
  fi
  want="$(grep -E "[[:space:]]\.?/?$2\$" "$sums" | awk '{print $1}' | head -n1 || true)"
  [ -n "$want" ] || { warn "SHA256SUMS 里没有 $2，跳过校验"; return 0; }
  got="$(sha256sum "$1" | awk '{print $1}')"
  [ "$want" = "$got" ] || die "校验失败：$2 期望 $want，实际 $got"
  ok "校验通过 $2"
}
fetch_package() { # fetch_package <文件名> <显式URL(可空)> → 只把下载到的路径打到 stdout，提示信息走 stderr
  local name="$1" explicit="${2:-}" url token=""
  # 先取 SHA256SUMS：既拿校验值，也用它给下载地址加内容令牌，
  # 避免 CDN（Cloudflare 等）把旧版本缓存住导致校验失败。
  local sums="$DOWNLOAD_DIR/SHA256SUMS"
  if [ "$VERIFY" = 1 ] && http_get "$BASE_URL/SHA256SUMS?v=$VERSION" "$sums" 2>/dev/null; then
    token="$(grep -E "[[:space:]]\.?/?$name\$" "$sums" | awk '{print $1}' | head -n1 | cut -c1-8 || true)"
    ok "校验值：$name → ${token:-未知}" >&2
  fi
  url="${explicit:-$BASE_URL/$name}"
  [ -n "$token" ] && url="$url?v=$token"
  {
    info "下载 $url"
    http_get "$url" "$DOWNLOAD_DIR/$name" || die "下载失败：$url"
    verify_sha256 "$DOWNLOAD_DIR/$name" "$name"
  } 1>&2
  printf '%s' "$DOWNLOAD_DIR/$name"
}
info() { printf '\033[36m==>\033[0m %s\n' "$*"; }
ok()   { printf '\033[32m ✓\033[0m %s\n' "$*"; }
warn() { printf '\033[33m ! \033[0m %s\n' "$*"; }

while [ $# -gt 0 ]; do
  case "$1" in
    --prefix)    [ $# -ge 2 ] || die "--prefix 需要一个目录参数"; PREFIX="$2"; shift 2 ;;
    --prefix=*)  PREFIX="${1#*=}"; shift ;;
    --bin-dir)   [ $# -ge 2 ] || die "--bin-dir 需要一个目录参数"; BIN_DIR="$2"; shift 2 ;;
    --bin-dir=*) BIN_DIR="${1#*=}"; shift ;;
    --system)    SYSTEM=1; PREFIX="/usr/local"; BIN_DIR="/usr/local/bin"; shift ;;
    --tar)       [ $# -ge 2 ] || die "--tar 需要一个文件参数"; TARBALL="$2"; shift 2 ;;
    --tar=*)     TARBALL="${1#*=}"; shift ;;
    --url)       [ $# -ge 2 ] || die "--url 需要一个地址参数"; TARBALL_URL="$2"; shift 2 ;;
    --url=*)     TARBALL_URL="${1#*=}"; shift ;;
    --base-url)  [ $# -ge 2 ] || die "--base-url 需要一个地址参数"; BASE_URL="$2"; shift 2 ;;
    --base-url=*) BASE_URL="${1#*=}"; shift ;;
    --flutter-extras) WITH_FLUTTER=1; shift ;;
    --no-verify) VERIFY=0; shift ;;
    --no-agent)  WITH_AGENT=0; shift ;;
    --no-dartrun) WITH_DARTRUN=0; shift ;;
    --no-plugins) WITH_PLUGINS=0; shift ;;
    --force-plugins) FORCE_PLUGINS=1; shift ;;
    --add-path)  ADD_PATH=1; shift ;;
    --force-agent-bin) FORCE_AGENT_BIN=1; shift ;;
    --uninstall) UNINSTALL=1; shift ;;
    -h|--help)
      if [ -n "$SELF_DIR" ] && [ -f "$SELF_DIR/install.sh" ]; then
        sed -n '2,40p' "$SELF_DIR/install.sh" | sed 's/^# \{0,1\}//'
      else
        cat <<'USAGE'
LVX (XRuntime) 安装脚本 —— 单条命令安装
  curl -fsSL https://lvx-office.com/install.sh | bash
  curl -fsSL https://lvx-office.com/install.sh | sudo bash -s -- --system
  curl -fsSL https://lvx-office.com/install.sh | bash -s -- --flutter-extras
  curl -fsSL https://lvx-office.com/install.sh | bash -s -- --uninstall
选项：--prefix DIR / --bin-dir DIR / --system / --tar FILE / --url URL /
      --base-url URL / --flutter-extras / --no-verify / --no-agent /
      --no-dartrun / --no-plugins / --force-plugins / --add-path /
      --force-agent-bin / --uninstall
USAGE
      fi
      exit 0 ;;
    *)           die "未知参数: $1（--help 看用法）" ;;
  esac
done

# ---------------------------------------------------------------- 卸载 -------
if [ "$UNINSTALL" = 1 ]; then
  [ -d "$PREFIX" ] || die "没有找到安装目录 $PREFIX"
  info "卸载 LVX（$PREFIX）"
  for b in lvx lvx-agent lvx_lvxc lvx_dartrun; do
    link="$BIN_DIR/$b"
    [ -e "$link" ] || [ -L "$link" ] || continue
    # 只删属于本次安装的：指向本前缀的符号链接，或与本前缀完全相同的副本
    if [ -L "$link" ] && [ "$(readlink "$link")" = "$PREFIX/bin/$b" ]; then
      rm -f "$link"; ok "移除 $link"
    elif [ -f "$link" ] && [ -f "$PREFIX/bin/$b" ] && cmp -s "$link" "$PREFIX/bin/$b"; then
      rm -f "$link"; ok "移除 $link"
    else
      warn "保留 $link（不属于 $PREFIX）"
    fi
  done
  if [ -f "$PREFIX/installed-files.txt" ]; then
    while IFS= read -r f; do [ -n "$f" ] && rm -f "$f"; done < "$PREFIX/installed-files.txt"
    ok "移除 $PREFIX 下的程序文件"
  else
    rm -rf "$PREFIX/bin" "$PREFIX/share/lvx"
  fi
  CLI_PTR="$HOME/.lvx/bin"
  if [ -f "$CLI_PTR" ] && grep -q "^$PREFIX/bin/lvx$" "$CLI_PTR" 2>/dev/null; then rm -f "$CLI_PTR"; ok "移除 $CLI_PTR"; fi
  [ -d "$PREFIX/flutter-extras" ] && rm -rf "$PREFIX/flutter-extras" && ok "移除 $PREFIX/flutter-extras（Flutter 扩展包）"
  rm -f "$PREFIX/installed-files.txt"
  # 收尾：只删我们自己创建、且已经空了的目录
  for d in "$PREFIX/plugins" "$PREFIX/bin/plugins" "$PREFIX/bin" \
           "$PREFIX/share/apps" "$PREFIX/share/doc/lvx" "$PREFIX/share/doc" \
           "$PREFIX/share" "$PREFIX"; do
    rmdir "$d" 2>/dev/null || true
  done
  [ -d "$PREFIX/plugins" ] && echo "插件目录 $PREFIX/plugins 里手动放的插件保留，需要请自行删除。"
  [ -d "$PREFIX/bin" ] && echo "提示：$PREFIX/bin 里还有别的东西，未删除。"
  echo "用户数据（~/.lvx/plugin、~/.lvx/apps、~/.lvx/sources.list）保留，如需彻底清除请手动删除 ~/.lvx。"
  exit 0
fi

# ------------------------------------------------------------ 找安装源 ------
SRC="${SELF_DIR:-$(pwd)}"
WORK=""
cleanup() {
  [ -n "$WORK" ] && rm -rf "$WORK"
  [ -n "$DOWNLOAD_DIR" ] && rm -rf "$DOWNLOAD_DIR"
}
trap cleanup EXIT

if [ ! -x "$SRC/bin/lvx" ]; then
  # 1) 脚本和压缩包放在一起：自动解包（离线可用）
  if [ -z "$TARBALL" ] && [ -n "$SELF_DIR" ]; then
    # 先找核心包（精确名字），再退回同目录其它包（排除 -flutter 扩展包）
    TARBALL="$(ls -1 "$SELF_DIR/lvx-$VERSION-linux-$ARCH.tar.gz" 2>/dev/null | head -n1 || true)"
    [ -n "$TARBALL" ] || TARBALL="$(ls -1 "$SELF_DIR"/lvx-"$VERSION"-linux-*.tar.gz 2>/dev/null | grep -v flutter | head -n1 || true)"
  fi
  # 2) 没有本地包：自动下载（单条命令安装）
  if [ -z "$TARBALL" ] || [ ! -f "$TARBALL" ]; then
    [ -n "$TARBALL" ] && warn "本地没有 $TARBALL，改为在线下载"
    DOWNLOAD_DIR="$(mktemp -d)"
    TARBALL="$(fetch_package "lvx-$VERSION-linux-$ARCH.tar.gz" "$TARBALL_URL")"
  fi
  if [ -n "$TARBALL" ] && [ -f "$TARBALL" ]; then
    info "解包 $TARBALL"
    WORK="$(mktemp -d)"
    tar -xzf "$TARBALL" -C "$WORK" || die "解包失败: $TARBALL"
    SRC="$(find "$WORK" -maxdepth 2 -type d -name 'lvx-*-linux-*' | head -n1)"
    [ -n "$SRC" ] && [ -x "$SRC/bin/lvx" ] || die "压缩包里没有 bin/lvx"
  else
    die "找不到安装包：可用 --tar 指定本地包，或让脚本自动下载（需要 curl/wget 与网络）。"
  fi
fi

# ------------------------------------------------------------ 预检 ----------
case "$ARCH" in
  x86_64|amd64) ;;
  *) die "这个包是 Linux x86_64 的，当前机器是 $ARCH。aarch64 请等对应构建。" ;;
esac
[ "$(id -u)" = 0 ] && [ "$PREFIX" != "/usr/local" ] && warn "以 root 装到 $PREFIX（通常无需 sudo）"
if [ "$SYSTEM" = 1 ] && [ "$(id -u)" != 0 ]; then
  die "系统安装需要 root：请用 sudo ./install.sh --system"
fi

for b in lvx lvx_lvxc; do
  [ -f "$SRC/bin/$b" ] || die "安装源缺少 bin/$b"
done
[ "$WITH_AGENT" = 1 ]    && [ -f "$SRC/bin/lvx-agent" ]   || true
[ "$WITH_DARTRUN" = 1 ]  && [ -f "$SRC/bin/lvx_dartrun" ] || true

# ------------------------------------------------------------ 安装 ----------
info "安装 LVX $VERSION → $PREFIX  （命令目录 $BIN_DIR）"
mkdir -p "$PREFIX/bin" "$PREFIX/bin/plugins" "$PREFIX/share/apps" "$PREFIX/share/doc/lvx" "$BIN_DIR"
# 插件被搜索的目录：系统装到 /usr/lib/lvx/plugins，用户装到 <前缀>/plugins
# （plugin_manager 认 <exe_dir>/plugins、$PWD/plugins、~/.local/lib/lvx/plugins、
#   ~/.lvx/plugin、/usr/lib/lvx/plugins）
if [ "$SYSTEM" = 1 ]; then PLUGIN_DIR="/usr/lib/lvx/plugins"; else PLUGIN_DIR="$PREFIX/plugins"; fi
mkdir -p "$PLUGIN_DIR"
ok "插件目录 $PLUGIN_DIR（丢 .so 进来即生效）"
: > "$PREFIX/installed-files.txt"

put() { # put <src> <dst-rel-to-prefix> <mode>
  local src="$1" rel="$2" mode="${3:-755}"
  install -D -m "$mode" "$src" "$PREFIX/$rel"
  printf '%s\n' "$PREFIX/$rel" >> "$PREFIX/installed-files.txt"
}

put "$SRC/bin/lvx"       "bin/lvx"
put "$SRC/bin/lvx_lvxc"  "bin/lvx_lvxc"
[ "$WITH_AGENT" = 1 ]   && put "$SRC/bin/lvx-agent"   "bin/lvx-agent"
[ "$WITH_DARTRUN" = 1 ] && put "$SRC/bin/lvx_dartrun" "bin/lvx_dartrun"

if [ -f "$SRC/share/apps/store.lvx" ]; then
  put "$SRC/share/apps/store.lvx" "share/apps/store.lvx" 644
  ok "示例商店 share/apps/store.lvx"
fi
if [ -d "$SRC/share/doc/lvx" ]; then
  for d in "$SRC"/share/doc/lvx/*; do
    [ -f "$d" ] || continue
    put "$d" "share/doc/lvx/$(basename "$d")" 644
  done
  ok "文档 share/doc/lvx/（$(ls -1 "$SRC"/share/doc/lvx | wc -l) 篇）"
fi
printf '%s\n' "$VERSION" > "$PREFIX/VERSION"
printf 'LVX %s  %s  installed %s\n' "$VERSION" "$ARCH" "$(date '+%F %T')" > "$PREFIX/INSTALLED.txt"
printf '%s\n%s\n' "$PREFIX/VERSION" "$PREFIX/INSTALLED.txt" >> "$PREFIX/installed-files.txt"
ok "程序 → $PREFIX/bin/"

if [ "$WITH_PLUGINS" = 1 ] && [ -d "$SRC/share/plugins" ]; then
  n=0; kept=0
  for p in "$SRC"/share/plugins/*.so; do
    [ -f "$p" ] || continue
    b="$(basename "$p")"
    if [ -f "$PLUGIN_DIR/$b" ] && [ "$FORCE_PLUGINS" != 1 ]; then kept=$((kept+1)); continue; fi
    install -m 755 "$p" "$PLUGIN_DIR/$b"
    printf '%s\n' "$PLUGIN_DIR/$b" >> "$PREFIX/installed-files.txt"
    n=$((n+1))
  done
  ok "官方插件 → $PLUGIN_DIR（安装 $n 个$([ "$kept" -gt 0 ] && echo "，已存在 $kept 个（--force-plugins 可覆盖）")）"
fi

# 可选：Flutter / Dart 运行时扩展包（kernel + flutter_assets）
if [ "$WITH_FLUTTER" = 1 ]; then
  [ -n "$DOWNLOAD_DIR" ] || DOWNLOAD_DIR="$(mktemp -d)"
  FNAME="lvx-$VERSION-linux-$ARCH-flutter.tar.gz"
  FBALL="$(fetch_package "$FNAME" "$FLUTTER_URL")"
  info "安装 Flutter/Dart 扩展包 → $PREFIX/flutter-extras"
  rm -rf "$PREFIX/flutter-extras"
  mkdir -p "$PREFIX/flutter-extras"
  tar -xzf "$FBALL" -C "$PREFIX/flutter-extras" --strip-components=1 || die "扩展包解包失败"
  ok "扩展包 → $PREFIX/flutter-extras（kernel + assets）"
fi

# 命令目录里的符号链接（LVX_PLUGIN_PATH 未设置时，插件就近搜索 <exe_dir>/plugins）
for b in lvx lvx_lvxc lvx_dartrun lvx-agent; do
  [ -f "$PREFIX/bin/$b" ] || continue
  ln -sfn "$PREFIX/bin/$b" "$BIN_DIR/$b"
done
ok "命令链接 → $BIN_DIR/{lvx,lvx_lvxc,lvx_dartrun,lvx-agent}"

# ~/.lvx/bin：一行文本，lvx-agent 用它定位 lvx CLI
CLI_PTR="$HOME/.lvx/bin"
mkdir -p "$HOME/.lvx"
if [ -d "$CLI_PTR" ]; then
  # 老安装把程序装进了 ~/.lvx/bin；此时该路径是目录，指针文件写不进去。
  warn "$CLI_PTR 是目录，跳过 CLI 指针；lvx-agent 会自动找到 $BIN_DIR/lvx"
elif [ -f "$CLI_PTR" ] && [ "$FORCE_AGENT_BIN" != 1 ]; then
  old="$(head -n1 "$CLI_PTR" 2>/dev/null || true)"
  if [ -n "$old" ] && [ "$old" != "$PREFIX/bin/lvx" ] && [ -x "$old" ]; then
    warn "$CLI_PTR 指向 $old（保留；要改成本次安装用 --force-agent-bin）"
  else
    printf '%s\n' "$PREFIX/bin/lvx" > "$CLI_PTR"; ok "$CLI_PTR → $PREFIX/bin/lvx"
  fi
else
  printf '%s\n' "$PREFIX/bin/lvx" > "$CLI_PTR"; ok "$CLI_PTR → $PREFIX/bin/lvx"
fi

# PATH
case ":$PATH:" in
  *":$BIN_DIR:"*) IN_PATH=1 ;;
  *)              IN_PATH=0 ;;
esac
if [ "$ADD_PATH" = 1 ]; then
  RC="$HOME/.bashrc"; MARK="# >>> lvx installer >>>"
  if ! grep -qF "$MARK" "$RC" 2>/dev/null; then
    { printf '\n%s\nexport PATH="%s:$PATH"\n# <<< lvx installer <<<\n' "$MARK" "$BIN_DIR" >> "$RC"; }
    ok "已写入 $RC（新开终端生效）"
  else
    ok "$RC 已配置过 PATH"
  fi
fi

# ------------------------------------------------------------ 自检 ----------
info "自检"
if "$PREFIX/bin/lvx" plugins >/tmp/.lvx_selfcheck.$$ 2>&1; then
  ok "lvx 可执行：$(head -n1 /tmp/.lvx_selfcheck.$$)"
else
  warn "lvx 自检未通过，输出："; sed 's/^/    /' /tmp/.lvx_selfcheck.$$ | head -n5
fi
rm -f /tmp/.lvx_selfcheck.$$
[ -x "$PREFIX/bin/lvx_lvxc" ] && ok "LVXB 工具链 lvx_lvxc 就绪"
[ "$WITH_AGENT" = 1 ] && [ -x "$PREFIX/bin/lvx-agent" ] && ok "网页商店代理 lvx-agent 就绪（默认 http://127.0.0.1:8765）"

AGENT_HINT=""
if [ "$WITH_AGENT" = 1 ]; then
  AGENT_HINT="    lvx-agent --port 8765             # 起网页商店代理（官网 store 用）"
fi
# 以 curl | bash 运行时 SELF_DIR 为空：给出等价的单条命令
if [ -n "$SELF_DIR" ] && [ -f "$SELF_DIR/install.sh" ]; then
  SELF_CMD="$SELF_DIR/install.sh"
else
  SELF_CMD="curl -fsSL https://lvx-office.com/install.sh | bash -s --"
fi
UNINSTALL_HINT="$SELF_CMD --uninstall"
EXTRAS_HINT=""
if [ "$WITH_FLUTTER" = 1 ]; then
  EXTRAS_HINT="  扩展包用法：
    export LVX_ASSETS=$PREFIX/flutter-extras/assets
    lvx_dartrun $PREFIX/flutter-extras/kernel/flutter_combined.dill --ui --hold 20"
fi

printf '\n\033[32mLVX %s 安装完成\033[0m\n\n' "$VERSION"
cat <<EOF
  马上试：
    lvx help                          # 命令总览
    lvx plugins                       # 已加载插件
    lvx store                         # 打开软件商店
$AGENT_HINT
  装插件：   lvx install <名字>        # 默认装到 ~/.lvx/plugin
  卸载：     $UNINSTALL_HINT
$EXTRAS_HINT
EOF

if [ "$IN_PATH" = 0 ]; then
  warn "$BIN_DIR 不在 PATH 里，当前终端请先执行："
  printf '    export PATH="%s:$PATH"\n' "$BIN_DIR"
  printf '  永久生效：%s --add-path（或把这行加进 ~/.bashrc）\n' "$SELF_CMD"
fi
