#!/usr/bin/env bash
# WinDesk Guard Linux 一键安装（本地包 / 远程下载均可）
#
# 远程：
#   curl -fsSL http://apt.tttsms.com/install-linux.sh | sudo bash
# 本地（已解压便携包）：
#   sudo bash install-linux.sh
set -euo pipefail

SERVICE_NAME="windesk-linux"
DOWNLOAD_URL="${WINDESK_DOWNLOAD_URL:-http://apt.tttsms.com/windesk-linux-portable-1.5.1.zip}"
INSTALL_ROOT="${WINDESK_INSTALL_ROOT:-/opt/windesk-linux}"

RED=$'\033[31m'
GRN=$'\033[32m'
YLW=$'\033[33m'
RST=$'\033[0m'
info() { echo "${GRN}[+]${RST} $*" >&2; }
warn() { echo "${YLW}[!]${RST} $*" >&2; }
fail() { echo "${RED}[-]${RST} $*" >&2; exit 1; }

TMP_DIR=""
cleanup() {
  if [[ -n "${TMP_DIR}" && -d "${TMP_DIR}" ]]; then
    rm -rf "${TMP_DIR}" || true
  fi
}
trap cleanup EXIT

# 提权（curl|bash 时请直接用 sudo bash）
if [[ "${EUID}" -ne 0 ]]; then
  if command -v sudo >/dev/null 2>&1 && [[ -f "${BASH_SOURCE[0]:-}" ]]; then
    info "需要 root，正在通过 sudo 重新执行…"
    exec sudo -E bash "${BASH_SOURCE[0]}" "$@"
  fi
  fail "请使用 root 运行：curl -fsSL http://apt.tttsms.com/install-linux.sh | sudo bash"
fi

DATA_DIR=""
SKIP_START=0
SHOW_ONLY=0
while [[ $# -gt 0 ]]; do
  case "$1" in
    --data) DATA_DIR="${2:-}"; shift 2 || fail "--data 需要目录" ;;
    --data=*) DATA_DIR="${1#*=}"; shift ;;
    --no-start) SKIP_START=1; shift ;;
    --show-pair) SHOW_ONLY=1; shift ;;
    -h|--help)
      cat <<EOF
用法: sudo bash install-linux.sh [选项]

选项:
  --data DIR     数据目录
  --show-pair    只打印配对串
  --no-start     安装服务但不保持运行
  -h, --help     帮助

环境变量:
  WINDESK_DOWNLOAD_URL   安装包地址（默认 ${DOWNLOAD_URL}）
  WINDESK_INSTALL_ROOT   安装目录（默认 ${INSTALL_ROOT}）
EOF
      exit 0
      ;;
    *) fail "未知参数: $1" ;;
  esac
done

has_agent() {
  local dir="$1"
  [[ -f "$dir/windesk-linux" ]] || [[ -d "$dir/windesk_linux" && -d "$dir/windesk" ]]
}

# 脚本真实路径（curl|bash 时 BASH_SOURCE 常为 /dev/fd/N，视为远程模式）
SCRIPT_PATH="${BASH_SOURCE[0]:-}"
SCRIPT_DIR=""
if [[ -n "$SCRIPT_PATH" && -f "$SCRIPT_PATH" && "$SCRIPT_PATH" != /dev/fd/* && "$SCRIPT_PATH" != /proc/self/fd/* ]]; then
  SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
fi

need_cmd() { command -v "$1" >/dev/null 2>&1 || fail "缺少命令：$1"; }

need_cmd systemctl
if ! command -v python3 >/dev/null 2>&1 && ! command -v python >/dev/null 2>&1; then
  fail "未找到 python3，请先安装 Python 3.10+"
fi

download_and_extract() {
  local fetch="" unzip_cmd=""
  if command -v curl >/dev/null 2>&1; then
    fetch=curl
  elif command -v wget >/dev/null 2>&1; then
    fetch=wget
  else
    fail "需要 curl 或 wget 以下载安装包"
  fi
  if command -v unzip >/dev/null 2>&1; then
    unzip_cmd="unzip"
  elif command -v busybox >/dev/null 2>&1; then
    unzip_cmd="busybox unzip"
  else
    fail "需要 unzip"
  fi

  info "未检测到本地 Agent，改为远程下载安装包"
  info "下载: $DOWNLOAD_URL"
  TMP_DIR="$(mktemp -d /tmp/windesk-install.XXXXXX)"
  local zip_path="${TMP_DIR}/pkg.zip"
  local extract="${TMP_DIR}/extract"
  mkdir -p "$extract"

  if [[ "$fetch" == "curl" ]]; then
    curl -fL --retry 3 --connect-timeout 15 -o "$zip_path" "$DOWNLOAD_URL" \
      || fail "下载失败：$DOWNLOAD_URL"
  else
    wget -O "$zip_path" "$DOWNLOAD_URL" || fail "下载失败：$DOWNLOAD_URL"
  fi
  [[ -s "$zip_path" ]] || fail "下载文件为空"

  info "解压…"
  # shellcheck disable=SC2086
  $unzip_cmd -qo "$zip_path" -d "$extract"

  local src=""
  if has_agent "$extract/windesk-linux-portable"; then
    src="$extract/windesk-linux-portable"
  elif has_agent "$extract"; then
    src="$extract"
  else
    for d in "$extract"/*; do
      if [[ -d "$d" ]] && has_agent "$d"; then
        src="$d"
        break
      fi
    done
  fi
  [[ -n "$src" ]] || fail "压缩包结构不正确，未找到 windesk-linux / windesk_linux"

  info "安装到 $INSTALL_ROOT"
  mkdir -p "$INSTALL_ROOT"
  systemctl stop "$SERVICE_NAME" >/dev/null 2>&1 || true

  if command -v rsync >/dev/null 2>&1; then
    rsync -a --delete --exclude 'data/' "$src"/ "$INSTALL_ROOT"/
  else
    shopt -s dotglob nullglob
    for item in "$src"/*; do
      local base
      base="$(basename "$item")"
      [[ "$base" == "data" ]] && continue
      rm -rf "${INSTALL_ROOT:?}/$base"
      cp -a "$item" "$INSTALL_ROOT/"
    done
    shopt -u dotglob nullglob
  fi
  mkdir -p "$INSTALL_ROOT/data"
  chmod +x "$INSTALL_ROOT/windesk-linux" 2>/dev/null || true
  chmod +x "$INSTALL_ROOT/install-linux.sh" 2>/dev/null || true
}

# 选择 ROOT：本地包目录，或下载到 /opt
ROOT=""
if [[ -n "$SCRIPT_DIR" ]] && has_agent "$SCRIPT_DIR"; then
  ROOT="$SCRIPT_DIR"
  info "使用本地安装包: $ROOT"
else
  download_and_extract
  ROOT="$INSTALL_ROOT"
fi

if [[ -z "$DATA_DIR" ]]; then
  DATA_DIR="$ROOT/data"
fi
mkdir -p "$DATA_DIR"

info "安装目录: $ROOT"
info "数据目录: $DATA_DIR"

PYTHON_BIN="$(command -v python3 || command -v python)"
info "Python: $PYTHON_BIN ($("$PYTHON_BIN" -c 'import sys; print("%d.%d"%sys.version_info[:2])'))"

LAUNCH=()
if [[ -f "$ROOT/windesk-linux" ]]; then
  chmod +x "$ROOT/windesk-linux" || true
  LAUNCH=("$ROOT/windesk-linux")
elif [[ -d "$ROOT/windesk_linux" && -d "$ROOT/windesk" ]]; then
  export PYTHONPATH="$ROOT${PYTHONPATH:+:$PYTHONPATH}"
  LAUNCH=("$PYTHON_BIN" -m windesk_linux)
else
  fail "未找到 Agent（需要 windesk-linux 或 windesk_linux/）"
fi

export WINDESK_DATA="$DATA_DIR"
export PYTHONPATH="${ROOT}${PYTHONPATH:+:$PYTHONPATH}"

run_agent() { "${LAUNCH[@]}" --data "$DATA_DIR" "$@"; }

if [[ "$SHOW_ONLY" -eq 1 ]]; then
  info "打印配对串…"
  run_agent --show-pair
  exit 0
fi

if command -v nft >/dev/null 2>&1; then
  info "防火墙后端: nftables"
elif command -v ufw >/dev/null 2>&1; then
  info "防火墙后端: ufw"
else
  warn "未检测到 nftables/ufw，白名单同步可能不可用"
fi

info "生成配对串…"
run_agent --show-pair || true

info "安装 systemd 服务 $SERVICE_NAME …"
run_agent --install-service || fail "安装服务失败"
if [[ "$SKIP_START" -eq 1 ]]; then
  systemctl stop "$SERVICE_NAME" >/dev/null 2>&1 || true
  warn "已按 --no-start 停止服务（仍已 enable 开机自启）"
fi

echo
info "安装完成"
echo "  目录: $ROOT"
echo "  状态: systemctl status $SERVICE_NAME"
echo "  日志: journalctl -u $SERVICE_NAME -f"
echo "  配对: 上方 JSON 仅未配对时显示一次；成功后明文销毁"
echo "  重置: ${LAUNCH[*]} --reset-pair --data $DATA_DIR"
echo
info "请立即复制上方配对 JSON 到手机 App「粘贴导入」（配对后无法再显示）。"
echo
systemctl --no-pager --full status "$SERVICE_NAME" || true
