#!/bin/sh
# Yegu 客户端的安装脚本（协议规范 §3.7）。由节点在 /install.sh 上提供：
#
#     curl -fsSL https://<节点域名>/install.sh | sh
#
# 它下载与这台机器相符的 yegu、核对校验和、装到 ~/.local/bin，然后启动 `yegu setup`：
# 账号、运行时、工作区都由 setup 来问。脚本自己不问任何问题，不需要 sudo。
# 再执行一次就是升级：换上新的程序，已有的 Agent 和配置不动。
#
# 可以用环境变量调整：
#   AITALK_INSTALL_DIR       装到哪个目录（默认 ~/.local/bin）
#   AITALK_NO_MODIFY_PATH=1  不去改 shell 的启动文件
#   AITALK_NO_SETUP=1        只安装，不启动 yegu setup
#   AITALK_NODE              加入哪个节点（默认是给出这个脚本的节点；设成空的就不指定）
#   AITALK_DOWNLOAD_BASE     从哪里下载（默认由节点给出）

# 写这个脚本的规矩：变量一律写成 ${name}。变量后面紧跟着中文的时候，单字节语言环境下的
# shell 会把中文的头一个字节算进变量名里，脚本就在那里停下。

set -eu

NODE_DEFAULT='yegu.ai'
BASE_DEFAULT='https://bfopenui5.oss-cn-hangzhou.aliyuncs.com/aitalk/client/v2026.10.14.6'

say() {
    printf '%s\n' "$*"
}

fail() {
    printf 'yegu 没有装上：%s\n' "$*" >&2
    exit 1
}

# 让新开的终端找得到 yegu：在 shell 的启动文件里加一行。认不出是哪种 shell 就只提示。
add_to_path() {
    dir="$1"
    # 在主目录下面的写成 $HOME/…：这一行换了用户名也还是对的
    case "${dir}" in
        "${HOME}"/*)
            rest="${dir#"${HOME}"/}"
            line="export PATH=\"\$HOME/${rest}:\$PATH\""
            ;;
        *) line="export PATH=\"${dir}:\$PATH\"" ;;
    esac
    rc=""
    if [ -z "${AITALK_NO_MODIFY_PATH:-}" ]; then
        case "${SHELL:-}" in
            */zsh) rc="${ZDOTDIR:-${HOME}}/.zshrc" ;;
            */bash) rc="${HOME}/.bash_profile" ;;
        esac
    fi
    if [ -z "${rc}" ]; then
        say "${dir} 不在 PATH 里。要直接用 yegu 这个命令，把这一行加进 shell 的启动文件："
        say "    ${line}"
        return
    fi
    if [ -f "${rc}" ] && grep -qF "${line}" "${rc}"; then
        return
    fi
    printf '\n# Yegu\n%s\n' "${line}" >>"${rc}"
    say "已把 ${dir} 加进 PATH（${rc}）。新开的终端里可以直接用 yegu。"
}

# 全部放在函数里，最后一行才调用：脚本下载到一半断了的话，什么都不会执行
main() {
    node="${AITALK_NODE-${NODE_DEFAULT}}"
    base="${AITALK_DOWNLOAD_BASE:-${BASE_DEFAULT}}"
    dir="${AITALK_INSTALL_DIR:-${HOME}/.local/bin}"

    command -v curl >/dev/null 2>&1 || fail "找不到 curl。"
    command -v shasum >/dev/null 2>&1 || fail "找不到 shasum。"

    os="$(uname -s)"
    arch="$(uname -m)"
    [ "${os}" = "Darwin" ] || fail "目前只支持 macOS（这台机器是 ${os}）。"
    # 在 Rosetta 下运行的终端会报 x86_64：按真实的处理器来
    if [ "${arch}" = "x86_64" ] && [ "$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)" = "1" ]; then
        arch="arm64"
    fi
    case "${arch}" in
        arm64) file="yegu-darwin-arm64" ;;
        x86_64) file="yegu-darwin-x86_64" ;;
        *) fail "不认识这台机器的处理器：${arch}。" ;;
    esac

    mkdir -p "${dir}" || fail "建不了目录 ${dir}。"
    # 下载到同一个目录里，装的时候只是改个名：正在运行的 aitalkd 不受影响
    tmp="$(mktemp -d "${dir}/.yegu-install.XXXXXX")" || fail "${dir} 写不了。"
    trap 'rm -rf "${tmp}"' EXIT
    trap 'exit 130' INT TERM

    say "正在下载 yegu（${file}）……"
    curl -fsSL "${base}/SHA256SUMS" -o "${tmp}/SHA256SUMS" || fail "下载不了 ${base}/SHA256SUMS。"
    curl -fL --progress-bar "${base}/${file}" -o "${tmp}/yegu" || fail "下载不了 ${base}/${file}。"

    expected="$(awk -v name="${file}" '$2 == name || $2 == "*" name { print $1; exit }' "${tmp}/SHA256SUMS")"
    [ -n "${expected}" ] || fail "校验和文件里没有 ${file}。"
    actual="$(shasum -a 256 "${tmp}/yegu" | awk '{ print $1 }')"
    [ "${expected}" = "${actual}" ] || fail "下载到的文件校验和不对，没有安装。"

    chmod 755 "${tmp}/yegu"
    # 运行得起来才装
    version="$("${tmp}/yegu" --version 2>/dev/null)" || fail "下载到的程序在这台机器上运行不了。"
    mv -f "${tmp}/yegu" "${dir}/yegu" || fail "写不了 ${dir}/yegu。"
    rm -rf "${tmp}"
    trap - EXIT
    say "已安装 ${version}：${dir}/yegu"

    case ":${PATH}:" in
        *":${dir}:"*) ;;
        *)
            add_to_path "${dir}"
            PATH="${dir}:${PATH}"
            export PATH
            ;;
    esac

    if [ -n "${AITALK_NO_SETUP:-}" ]; then
        say "接下来执行：yegu setup${node:+ ${node}}"
        return
    fi
    say ""
    # 用 curl | sh 执行时，标准输入是这个脚本本身：setup 要问的话得从终端读
    if [ -t 0 ]; then
        exec "${dir}/yegu" setup ${node:+"${node}"}
    elif (exec </dev/tty) 2>/dev/null; then
        exec "${dir}/yegu" setup ${node:+"${node}"} </dev/tty
    else
        say "这里没有终端，问不了问题。接下来在终端里执行：yegu setup${node:+ ${node}}"
    fi
}

main "$@"
