#!/usr/bin/env bash
# SiteStats 在线一键安装（适合"curl ... | bash"方式）
#
# 用法（在目标服务器上以 root 执行）：
#   curl -fsSL https://<你的下载地址>/install-online.sh | bash -s -- [--sites a.cn b.cn]
#
# 环境变量：
#   SITESTATS_URL  二进制下载地址（默认见下方 BASE）
#   SITESTATS_BIN  已下载好的本地二进制路径（给了就不再下载）
#
# 它会：下载二进制 → 安装 → 注册两个 systemd 服务（采集器 + Web）→ 注入 nginx 日志推送 → 打印访问地址。
set -euo pipefail

BASE="${SITESTATS_URL:-https://download.gzmowo.cn/sitestats}"
ARCH_OK=0

log()  { echo "[sitestats-install] $*"; }
die()  { echo "[sitestats-install][错误] $*" >&2; exit 1; }

[ "$(id -u)" = "0" ] || die "需要 root（请用 sudo bash 或 root 身份运行）"

# 平台判断
case "$(uname -s)" in
  Linux) OS=linux ;;
  *) die "目前仅支持 Linux（Windows 版请用 zip 包手工部署）" ;;
esac
case "$(uname -m)" in
  x86_64|amd64) ARCH=amd64 ;;
  aarch64|arm64) ARCH=arm64 ;;
  *) die "不支持的 CPU 架构：$(uname -m)" ;;
esac

TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT

# 下载（curl 优先，wget 兜底）
dl() {  # dl <相对路径> <输出文件>
  local url="$BASE/$1" out="$2"
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL --connect-timeout 15 "$url" -o "$out" || return 1
  else
    wget -qO "$out" --timeout=20 "$url" || return 1
  fi
}

# 校验和（有 SHA256SUMS 就校验，防止下载被截断/篡改）
verify() {  # verify <文件名>
  local f="$1"
  [ -s "$TMP/SHA256SUMS" ] || return 0
  local want got
  want=$(grep -E "[[:space:]]${f}$" "$TMP/SHA256SUMS" | awk '{print $1}' | head -1)
  [ -z "$want" ] && return 0
  got=$(sha256sum "$TMP/$f" | awk '{print $1}')
  [ "$want" = "$got" ] || die "校验失败：$f（期望 ${want:0:12}…，实际 ${got:0:12}…）"
}

if [ -n "${SITESTATS_BIN:-}" ]; then
  log "使用本地二进制：$SITESTATS_BIN"
  cp "$SITESTATS_BIN" "$TMP/sitestats"
else
  die_missing=0
  dl SHA256SUMS "$TMP/SHA256SUMS" || true
  log "下载：$BASE/sitestats-${OS}-${ARCH}"
  dl "sitestats-${OS}-${ARCH}" "$TMP/sitestats-${OS}-${ARCH}" || die_missing=1
  [ "$die_missing" = 0 ] || die "下载失败：$BASE/sitestats-${OS}-${ARCH}（可用 SITESTATS_URL 指定其它下载源）"
  verify "sitestats-${OS}-${ARCH}"
  mv "$TMP/sitestats-${OS}-${ARCH}" "$TMP/sitestats"
fi
chmod +x "$TMP/sitestats"

log "版本：$("$TMP/sitestats" version 2>/dev/null || echo 未知)"

# 安装目录与脚本
PREFIX=/usr/local/sitestats
DATA=/var/lib/sitestats
mkdir -p "$PREFIX" "$DATA"

# 若服务器上已有安装包自带的脚本，优先用旧的；否则用下载的口径生成
install -m 0755 "$TMP/sitestats" "$PREFIX/sitestats"

# 下载配套脚本（安装包同目录）
for f in inject-logs.sh sitestats-log-format.conf sitestats.service sitestats-web.service show-info.sh install-online.sh; do
  dl "$f" "$TMP/$f" || true
  verify "$f" || true
done
[ -s "$TMP/inject-logs.sh" ] || die "配套脚本下载失败，请改用离线包安装（tar.gz）"
chmod +x "$TMP/inject-logs.sh"
install -m 0755 "$TMP/inject-logs.sh" "$PREFIX/inject-logs.sh"
install -m 0644 "$TMP/sitestats-log-format.conf" "$PREFIX/sitestats-log-format.conf"
[ -s "$TMP/show-info.sh" ] && { chmod +x "$TMP/show-info.sh"; install -m 0755 "$TMP/show-info.sh" "$PREFIX/show-info.sh"; }
# 装一份安装脚本本身：便于以后升级、放开监听（--listen-public）
if [ -s "$TMP/install-online.sh" ]; then
  install -m 0755 "$TMP/install-online.sh" "$PREFIX/install-online.sh"
elif [ -f "$0" ]; then
  install -m 0755 "$0" "$PREFIX/install-online.sh" 2>/dev/null || true
fi

# 采集器服务
cat > /etc/systemd/system/sitestats.service <<'EOF'
[Unit]
Description=SiteStats 网站统计采集器
After=network.target nginx.service
Wants=nginx.service

[Service]
Type=simple
ExecStart=/usr/local/sitestats/sitestats listen -site default -db /var/lib/sitestats/sitestats.db -detail -sock /tmp/sitestats.sock -mem 256 -route
Restart=always
RestartSec=5
LimitNOFILE=65535
NoNewPrivileges=true
ProtectSystem=full
ReadWritePaths=/var/lib/sitestats /tmp
StandardOutput=append:/var/log/sitestats.log
StandardError=append:/var/log/sitestats.log

[Install]
WantedBy=multi-user.target
EOF

# ---------- 监听地址：默认只监听本机；端口被占用时自动改用其它可用端口 ----------
CENTER="${SITESTATS_CENTER:-}"
NODE_TOKEN="${SITESTATS_TOKEN:-}"
# 中心站点参数解析（必须放在服务安装之前）
ARGS0=("$@")
for ((ci=0; ci<${#ARGS0[@]}; ci++)); do
  case "${ARGS0[$ci]}" in
    --center)   CENTER="${ARGS0[$((ci+1))]:-}" ;;
    --token)    NODE_TOKEN="${ARGS0[$((ci+1))]:-}" ;;
    --center=*) CENTER="${ARGS0[$ci]#*=}" ;;
    --token=*)  NODE_TOKEN="${ARGS0[$ci]#*=}" ;;
  esac
done

LISTEN_IP=127.0.0.1
BASE_PORT=${SITESTATS_PORT:-8899}
for a in "$@"; do
  case "$a" in
    --listen-public) LISTEN_IP=0.0.0.0 ;;
    --center=*)  CENTER="${a#*=}" ;;
    --token=*)   NODE_TOKEN="${a#*=}" ;;
    --listen=*|--addr=*) LISTEN_IP="${a#*=}"; BASE_PORT="${LISTEN_IP##*:}"; LISTEN_IP="${LISTEN_IP%%:*}" ;;
  esac
done

# 端口可用判定：① 当前已装服务用的端口 ② 本服务进程占的端口 → 都算可用（重装/升级直接复用）
port_free_or_mine() {
  local p=$1 cur
  cur=$(sed -n 's/.*-addr [^:]*:\([0-9]*\).*/\1/p' /etc/systemd/system/sitestats-web.service 2>/dev/null | head -1)
  [ -n "$cur" ] && [ "$cur" = "$p" ] && return 0
  ! ss -lntH 2>/dev/null | awk '{print $4}' | grep -q ":${p}$"
}

PORT=$BASE_PORT
if ! port_free_or_mine "$PORT"; then
  for i in $(seq 1 200); do
    if port_free_or_mine "$((BASE_PORT+i))"; then
      log "端口 $BASE_PORT 已被其它程序占用，自动改用 $((BASE_PORT+i))"
      PORT=$((BASE_PORT+i)); break
    fi
  done
fi
LISTEN_ADDR="$LISTEN_IP:$PORT"
log "界面监听地址：$LISTEN_ADDR"

# Web 服务（只监听本机，外网通过 nginx 反代 + HTTPS 暴露）
cat > /etc/systemd/system/sitestats-web.service <<'EOF'
[Unit]
Description=SiteStats Web 界面与 API
After=network.target sitestats.service
Wants=sitestats.service

[Service]
Type=simple
ExecStart=/usr/local/sitestats/sitestats serve -db /var/lib/sitestats/sitestats.db -detail-dir /var/lib/sitestats -addr 127.0.0.1:8899
Restart=always
RestartSec=5
NoNewPrivileges=true
ProtectSystem=full
ReadWritePaths=/var/lib/sitestats
StandardOutput=append:/var/log/sitestats-web.log
StandardError=append:/var/log/sitestats-web.log

[Install]
WantedBy=multi-user.target
EOF

sed -i "s|-addr 127.0.0.1:8899|-addr $LISTEN_ADDR|" /etc/systemd/system/sitestats-web.service
systemctl daemon-reload
systemctl enable --now sitestats.service >/dev/null 2>&1
systemctl enable sitestats-web.service >/dev/null 2>&1
systemctl restart sitestats-web.service >/dev/null 2>&1   # 端口/配置变了必须重启才生效

# ---------- 中心站点：探针上报服务 ----------
if [ -n "$CENTER" ] && [ -n "$NODE_TOKEN" ]; then
  cat > /etc/systemd/system/sitestats-report.service <<EOF
[Unit]
Description=SiteStats 探针上报（中心站点）
After=network-online.target sitestats.service
Wants=network-online.target

[Service]
Type=simple
ExecStart=$PREFIX/sitestats report -center $CENTER -token $NODE_TOKEN -db /var/lib/sitestats/sitestats.db -name $(hostname)
Restart=always
RestartSec=10
MemoryMax=256M

[Install]
WantedBy=multi-user.target
EOF
  systemctl daemon-reload
  systemctl enable --now sitestats-report.service >/dev/null 2>&1
  echo "[sitestats-install] 中心站点上报已开启：$CENTER"
elif [ -n "$CENTER" ] && [ -z "$NODE_TOKEN" ]; then
  echo "[sitestats-install] 提示：用了 --center 但没给 --token（节点令牌在中心站「中心站点」页添加节点后获取）"
fi

sleep 1

if systemctl is-active --quiet sitestats.service && systemctl is-active --quiet sitestats-web.service; then
  log "采集器 + Web 均已启动 ✅"
else
  log "服务未全部启动，日志如下："
  journalctl -u sitestats -n 10 --no-pager 2>/dev/null | sed 's/^/  /'
  tail -10 /var/log/sitestats.log 2>/dev/null | sed 's/^/  /'
  tail -10 /var/log/sitestats-web.log 2>/dev/null | sed 's/^/  /'
  exit 1
fi

# 注入 nginx（可用 --no-inject 跳过）
INJECT=1
ARGS=("$@")
for a in "${ARGS[@]:-}"; do
  case "$a" in
    --no-inject) INJECT=0 ;;
  esac
done
# "--center <url>" / "--token <tok>" 分离写法：把值吃进来（避免被当成域名）
for ((ai=0; ai<${#ARGS[@]}; ai++)); do
  case "${ARGS[$ai]}" in
    --center) CENTER="${ARGS[$((ai+1))]:-}" ;;
    --token)  NODE_TOKEN="${ARGS[$((ai+1))]:-}" ;;
  esac
done
SITES=()
INJECT_ALL=0
skip_next=0
for a in "${ARGS[@]:-}"; do
  if [ "$skip_next" = 1 ]; then SITES+=("$a"); skip_next=0; continue; fi
  case "$a" in
    --sites) skip_next=1 ;;
    --inject-all) INJECT_ALL=1 ;;
    --no-inject|--listen-public) ;;                 # 已处理过的开关，别当成域名
    --listen=*|--addr=*) ;;                         # 同上
    *) SITES+=("$a") ;;
  esac
done

if [ "$INJECT" = 1 ]; then
  if [ ${#SITES[@]} -gt 0 ]; then
    bash "$PREFIX/inject-logs.sh" --inject "${SITES[@]}" || log "注入失败，可稍后手工执行：$PREFIX/inject-logs.sh --inject <域名>"
  elif [ "$INJECT_ALL" = 1 ] || [ ${#SITES[@]} -eq 0 ]; then
    bash "$PREFIX/inject-logs.sh" --inject-all || log "注入失败，可稍后手工执行：$PREFIX/inject-logs.sh --inject-all"
  fi
fi

# 放行本机防火墙（只在放开监听时做）
if [ "$LISTEN_IP" != "127.0.0.1" ]; then
  if command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -q "Status: active"; then
    ufw allow "$PORT"/tcp >/dev/null 2>&1 && log "已放行 ufw 端口 $PORT/tcp"
  fi
  if command -v firewall-cmd >/dev/null 2>&1 && systemctl is-active --quiet firewalld; then
    firewall-cmd --permanent --add-port="$PORT"/tcp >/dev/null 2>&1 && firewall-cmd --reload >/dev/null 2>&1 && log "已放行 firewalld 端口 $PORT/tcp"
  fi
fi

if [ -x "$PREFIX/show-info.sh" ]; then
  bash "$PREFIX/show-info.sh"
else
  cat <<INFO

------------------------------------------------------------
SiteStats 安装完成
  本机访问：http://127.0.0.1:$PORT
  访问密码：登录后首次打开界面自行设置
  撤销日志注入：bash $PREFIX/inject-logs.sh --rollback
  卸载：systemctl disable --now sitestats sitestats-web; rm -rf $PREFIX $DATA
------------------------------------------------------------
INFO
fi
