#!/usr/bin/env bash
# 作者：Jincheng
# 文件描述：QKpanel Linux 一键安装脚本
# 创建日期：2026-06-13
# 许可证：MIT

set -euo pipefail

INSTALL_DIR="${QKPANEL_INSTALL_DIR:-/opt/qkpanel}"
CONFIG_FILE="${INSTALL_DIR}/config/config.yaml"
DATA_DIR="${INSTALL_DIR}/data"
SERVICE_NAME="qkpanel"
GITHUB_REPO="${QKPANEL_GITHUB_REPO:-aspect-developer/qkpanel}"
VERSION="${QKPANEL_VERSION:-latest}"
DOWNLOAD_URL="${QKPANEL_DOWNLOAD_URL:-}"
LOCAL_BINARY=""
SKIP_FIREWALL="${QKPANEL_SKIP_FIREWALL:-0}"

usage() {
  cat <<EOF
Usage: install.sh [OPTIONS]

Options:
  --local PATH    使用本地二进制文件，跳过下载
  --version VER   指定版本号（默认 latest）
  --help          显示帮助

Environment:
  QKPANEL_INSTALL_DIR   安装目录（默认 /opt/qkpanel）
  QKPANEL_DOWNLOAD_URL  自定义二进制下载地址
  QKPANEL_VERSION       版本号
  QKPANEL_SKIP_FIREWALL 设为 1 跳过防火墙配置
EOF
}

log() { echo "[QKpanel] $*"; }
die() { echo "[QKpanel] ERROR: $*" >&2; exit 1; }

while [[ $# -gt 0 ]]; do
  case "$1" in
    --local)
      LOCAL_BINARY="${2:-}"
      shift 2
      ;;
    --version)
      VERSION="${2:-}"
      shift 2
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      die "Unknown option: $1"
      ;;
  esac
done

if [[ "$(id -u)" -ne 0 ]]; then
  die "请使用 root 权限运行: sudo bash install.sh"
fi

detect_arch() {
  local arch
  arch="$(uname -m)"
  case "$arch" in
    x86_64|amd64) echo "amd64" ;;
    aarch64|arm64) echo "arm64" ;;
    *) die "不支持的架构: $arch" ;;
  esac
}

detect_os() {
  if [[ -f /etc/os-release ]]; then
    # shellcheck source=/dev/null
    . /etc/os-release
    case "${ID:-}" in
      ubuntu|debian|centos|rhel|rocky|almalinux|fedora) return 0 ;;
      *) die "不支持的操作系统: ${ID:-unknown}" ;;
    esac
  else
    die "无法检测操作系统"
  fi
}

resolve_download_url() {
  local arch="$1"
  if [[ -n "$DOWNLOAD_URL" ]]; then
    echo "$DOWNLOAD_URL"
    return
  fi

  local ver="$VERSION"
  if [[ "$ver" == "latest" ]]; then
    ver="$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" | grep '"tag_name"' | head -1 | cut -d'"' -f4 || true)"
    [[ -z "$ver" ]] && ver="v1.0.0"
  fi

  echo "https://github.com/${GITHUB_REPO}/releases/download/${ver}/qkpanel-linux-${arch}"
}

generate_jwt_secret() {
  if command -v openssl >/dev/null 2>&1; then
    openssl rand -hex 32
  else
    tr -dc 'a-zA-Z0-9' </dev/urandom | head -c 64
  fi
}

get_server_ip() {
  local ip=""
  ip="$(hostname -I 2>/dev/null | awk '{print $1}' || true)"
  if [[ -z "$ip" ]]; then
    ip="$(curl -fsSL --max-time 3 https://api.ipify.org 2>/dev/null || echo "127.0.0.1")"
  fi
  echo "$ip"
}

open_firewall() {
  [[ "$SKIP_FIREWALL" == "1" ]] && return 0

  if command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -qi active; then
    ufw allow 9999/tcp comment 'QKpanel' >/dev/null 2>&1 || true
    log "已尝试通过 ufw 开放 9999/tcp"
  elif command -v firewall-cmd >/dev/null 2>&1; then
    firewall-cmd --permanent --add-port=9999/tcp >/dev/null 2>&1 || true
    firewall-cmd --reload >/dev/null 2>&1 || true
    log "已尝试通过 firewalld 开放 9999/tcp"
  fi
}

install_binary() {
  local arch="$1"
  local tmp
  tmp="$(mktemp)"
  trap 'rm -f "$tmp"' RETURN

  if [[ -n "$LOCAL_BINARY" ]]; then
    [[ -f "$LOCAL_BINARY" ]] || die "本地二进制不存在: $LOCAL_BINARY"
    cp "$LOCAL_BINARY" "$tmp"
  else
    local url
    url="$(resolve_download_url "$arch")"
    log "下载 QKpanel: $url"
    if ! curl -fsSL "$url" -o "$tmp"; then
      die "下载失败。可设置 QKPANEL_DOWNLOAD_URL 或使用 --local 指定本地二进制"
    fi
  fi

  mkdir -p "${INSTALL_DIR}" "${INSTALL_DIR}/config" "${DATA_DIR}"
  install -m 755 "$tmp" "${INSTALL_DIR}/qkpanel"
}

write_config() {
  local jwt_secret
  jwt_secret="$(generate_jwt_secret)"

  if [[ -f "$CONFIG_FILE" ]]; then
    log "保留已有配置文件: $CONFIG_FILE"
    return
  fi

  cat >"$CONFIG_FILE" <<EOF
# QKpanel 生产环境配置（由 install.sh 生成）

server:
  port: 9999
  mode: release

database:
  path: ${DATA_DIR}/qkpanel.db

storage:
  data_dir: ${DATA_DIR}
  site_dir: ""

jwt:
  secret: ${jwt_secret}
  expire_hour: 24
EOF
  chmod 600 "$CONFIG_FILE"
  log "已生成配置文件: $CONFIG_FILE"
}

install_systemd() {
  cat >/etc/systemd/system/${SERVICE_NAME}.service <<EOF
[Unit]
Description=QKpanel Server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
WorkingDirectory=${INSTALL_DIR}
ExecStart=${INSTALL_DIR}/qkpanel -config ${CONFIG_FILE}
Restart=always
RestartSec=5
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

  systemctl daemon-reload
  systemctl enable "${SERVICE_NAME}"
  systemctl restart "${SERVICE_NAME}"
}

main() {
  detect_os
  local arch
  arch="$(detect_arch)"

  log "开始安装 QKpanel (${arch})..."

  install_binary "$arch"
  write_config
  install_systemd
  open_firewall

  sleep 2
  if systemctl is-active --quiet "${SERVICE_NAME}"; then
    log "服务已启动"
  else
    die "服务启动失败，请检查: journalctl -u ${SERVICE_NAME} -n 50"
  fi

  local ip
  ip="$(get_server_ip)"

  echo ""
  echo "=========================================="
  echo "  QKpanel 安装成功！"
  echo "=========================================="
  echo "  访问地址: http://${ip}:9999"
  echo "  默认账号: admin"
  echo "  默认密码: changeme123"
  echo "  请首次登录后立即修改密码"
  echo "=========================================="
  echo ""
  echo "管理命令:"
  echo "  systemctl status ${SERVICE_NAME}"
  echo "  systemctl restart ${SERVICE_NAME}"
  echo "  journalctl -u ${SERVICE_NAME} -f"
}

main "$@"
