#!/usr/bin/env bash
# ============================================================
#  酒馆（SillyTavern）控制脚本  ——  DSH 机 192.168.31.76
#  访问：http://192.168.31.76:8000
#  用法：bash ~/Downloads/sillytavern-ctl.sh {start|stop|restart|status|log|test|update|info}
#  托管：systemd 单元 sillytavern.service（Restart=always + 开机自启）
# ============================================================
set -uo pipefail

UNIT="sillytavern.service"
DIR="/home/zyw/SillyTavern"
PORT=8000
PROXY="http://127.0.0.1:10809"      # v2ray HTTP 入口（git/npm 用）
NPX_BIN="/usr/bin/node"
SUDO_PW="yueling408"

s() { echo "$SUDO_PW" | sudo -S "$@" 2>/dev/null; }

wait_up() {  # 等端口起来，最多 60s
    for _ in $(seq 1 30); do
        sleep 2
        ss -ltn 2>/dev/null | grep -q ":${PORT} " && return 0
    done
    return 1
}

case "${1:-status}" in
start)
    s systemctl start "$UNIT"
    wait_up && echo "✅ 已启动： http://192.168.31.76:${PORT}" || echo "⚠️ 60s 内未监听 ${PORT}，看日志：$0 log"
    ;;
stop)
    s systemctl stop "$UNIT"
    echo "🛑 已停止 $UNIT"
    ;;
restart)
    s systemctl restart "$UNIT"
    wait_up && echo "✅ 已重启： http://192.168.31.76:${PORT}" || echo "⚠️ 60s 内未监听 ${PORT}，看日志：$0 log"
    ;;
status)
    echo "单元状态: $(systemctl is-active "$UNIT" 2>/dev/null) / 开机自启: $(systemctl is-enabled "$UNIT" 2>/dev/null)"
    ss -ltnp 2>/dev/null | grep ":${PORT} " || echo "端口 ${PORT} 未监听"
    echo -n "本机探活: "; curl -s -o /dev/null -w "HTTP %{http_code}\n" --max-time 8 --noproxy '*' "http://127.0.0.1:${PORT}/"
    echo -n "局域网探活: "; curl -s -o /dev/null -w "HTTP %{http_code}\n" --max-time 8 --noproxy '*' "http://192.168.31.76:${PORT}/"
    echo -n "版本: "; curl -s --max-time 8 --noproxy '*' "http://127.0.0.1:${PORT}/version"
    echo
    echo -n "后端 LLM: "; curl -s --max-time 6 --noproxy '*' http://192.168.31.31:8080/v1/models \
        | python3 -c "import sys,json;print(', '.join(m['id'] for m in json.load(sys.stdin)['data']))" 2>/dev/null \
        || echo "⚠️ GPU 机 8080 未响应（在 GPU 机跑 bash ~/switch-llm.sh 启动）"
    ;;
log)
    tail -n "${2:-40}" /home/zyw/SillyTavern/sillytavern.log
    ;;
test)
    echo "=== 端到端自检：酒馆 → GPU 机 LLM ==="
    CK=$(mktemp); T=$(curl -s --max-time 10 --noproxy '*' -c "$CK" "http://127.0.0.1:${PORT}/csrf-token" \
        | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])" 2>/dev/null)
    [ -z "${T:-}" ] && { echo "❌ 取不到 CSRF token，服务可能没起"; rm -f "$CK"; exit 1; }
    curl -s --max-time 180 --noproxy '*' -b "$CK" -H "X-CSRF-Token: $T" -H 'Content-Type: application/json' \
        "http://127.0.0.1:${PORT}/api/backends/chat-completions/generate" -d '{
        "chat_completion_source":"custom",
        "custom_url":"http://192.168.31.31:8080/v1",
        "model":"bucoid-heretic-27b",
        "messages":[{"role":"user","content":"用一句话证明你在正常工作。"}],
        "max_tokens":150,"temperature":1.0,"stream":false}' \
    | python3 -c "
import sys,json
try:
    d=json.load(sys.stdin); c=d['choices'][0]['message']
    print('✅ 链路正常，模型回复 =', repr(c.get('content'))[:200])
    print('   usage =', d.get('usage'))
except Exception as e:
    print('❌ 调用失败：', e); sys.exit(1)
"
    rm -f "$CK"
    ;;
update)
    echo "=== 更新酒馆（GitHub 走代理）==="
    export https_proxy="$PROXY" http_proxy="$PROXY"
    cd "$DIR" || exit 1
    git fetch --tags --depth 1 origin 2>&1 | tail -2
    LATEST=$(git tag -l | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1)
    echo "当前: $(node -p "require('./package.json').version")   最新稳定版: ${LATEST}"
    if [ "$(node -p "require('./package.json').version")" = "$LATEST" ]; then
        echo "已是最新，跳过。"; exit 0
    fi
    git checkout -q "$LATEST" && echo "已切到 $LATEST，装依赖…"
    npm install --no-audit --no-fund --loglevel=error 2>&1 | tail -3
    s systemctl restart "$UNIT"
    wait_up && echo "✅ 更新完成： http://192.168.31.76:${PORT}" || echo "⚠️ 启动异常，看日志"
    ;;
info)
    cat <<EOF
酒馆 SillyTavern
  访问地址   http://192.168.31.76:${PORT}
  安装目录   ${DIR}
  数据目录   ${DIR}/data/default-user   （角色卡 characters/、聊天记录 chats/、设置 settings.json）
  配置文件   ${DIR}/config.yaml
  日志       ${DIR}/sillytavern.log     （journalctl -u sillytavern 亦可）
  后端 LLM   http://192.168.31.31:8080/v1  模型 bucoid-heretic-27b（GPU 机 llama.cpp）
             启动命令（GPU 机）： bash ~/switch-llm.sh
  出站代理   socks5://127.0.0.1:10808（GitHub 等走代理；局域网 IP 在 config.yaml 的 bypass 里直连）
EOF
    ;;
*)
    echo "用法：bash $0 {start|stop|restart|status|log [行数]|test|update|info}"
    ;;
esac
