#!/usr/bin/env bash
# 比特骆驼自动化对冲系统 部署管理器（工程 eth_hedge_sim）
# 部署环境: Ubuntu 22.04 LTS
#
# 新服务器(免克隆):
#   curl -fsSL https://git.bz121.com/dekun/eth_hedge_sim/raw/branch/main/deploy/manage.sh | bash
#
# 已安装:
#   bash /opt/eth_hedge_sim/deploy/manage.sh
#
set -e
if [ -n "${BASH_VERSION:-}" ]; then
  set -o pipefail
fi

INSTALL_ROOT="${INSTALL_ROOT:-/opt/eth_hedge_sim}"
GIT_URL="${GIT_URL:-https://git.bz121.com/dekun/eth_hedge_sim.git}"
GIT_BRANCH="${GIT_BRANCH:-main}"

# curl | bash 时脚本从 stdin 执行,BASH_SOURCE[0] 为空;须先安全探测再 set -u
_script_src="${BASH_SOURCE[0]:-}"
if [[ -n "${_script_src}" && -f "${_script_src}" ]]; then
  DEPLOY_DIR="$(cd "$(dirname "${_script_src}")" && pwd)"
  REPO_ROOT="$(cd "${DEPLOY_DIR}/.." && pwd)"
  LIB_DIR="${DEPLOY_DIR}/lib"
else
  DEPLOY_DIR=""
  REPO_ROOT=""
  LIB_DIR=""
fi
unset _script_src

set -u

repo_ready() {
  [[ -f "${1}/deploy/manage.sh" && -f "${1}/deploy/pull_and_restart.sh" && -d "${1}/deploy/lib" ]]
}

ensure_git_cli() {
  if command -v git >/dev/null 2>&1; then
    return 0
  fi
  if command -v apt-get >/dev/null 2>&1; then
    export DEBIAN_FRONTEND=noninteractive
    # 新机常撞 unattended-upgrades 占锁；最多等 10 分钟
    local waited=0
    while pgrep -x unattended-upgr >/dev/null 2>&1 \
      || pgrep -x apt-get >/dev/null 2>&1 \
      || pgrep -x apt >/dev/null 2>&1 \
      || pgrep -x dpkg >/dev/null 2>&1 \
      || { command -v fuser >/dev/null 2>&1 && fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; }; do
      if [[ "${waited}" -eq 0 ]]; then
        echo "等待 apt 锁释放（unattended-upgrades）…"
      fi
      if [[ "${waited}" -ge 600 ]]; then
        echo "错误: 等待 apt 锁超时，请稍后再试" >&2
        exit 1
      fi
      sleep 5
      waited=$((waited + 5))
    done
    apt-get update -qq
    apt-get install -y git ca-certificates curl
  else
    echo "错误: 未找到 git" >&2
    exit 1
  fi
}

sync_repo_if_present() {
  local root="$1"
  if [[ -d "${root}/.git" ]] && command -v git >/dev/null 2>&1; then
    git -C "${root}" fetch --all --prune 2>/dev/null || true
    git -C "${root}" checkout "${GIT_BRANCH}" 2>/dev/null || true
    git -C "${root}" pull --ff-only origin "${GIT_BRANCH}" 2>/dev/null \
      || git -C "${root}" pull --ff-only 2>/dev/null \
      || true
  fi
}

# 旧目录已存在但缺 manage.sh：尽量 git pull / 修复后切到仓库内脚本
heal_existing_install() {
  local root="$1"
  echo "检测到已有目录但缺少管理脚本: ${root}"
  echo "尝试同步最新代码…"
  ensure_git_cli

  if [[ -d "${root}/.git" ]]; then
    sync_repo_if_present "${root}"
    if repo_ready "${root}"; then
      echo "同步成功，切换到仓库内 manage.sh"
      exec bash "${root}/deploy/manage.sh" "$@" </dev/tty
    fi
    echo "git pull 后仍不完整，尝试强制对齐 origin/${GIT_BRANCH} …"
    git -C "${root}" fetch origin "${GIT_BRANCH}" || true
    git -C "${root}" reset --hard "origin/${GIT_BRANCH}" || true
    if repo_ready "${root}"; then
      echo "对齐成功，切换到仓库内 manage.sh"
      exec bash "${root}/deploy/manage.sh" "$@" </dev/tty
    fi
  fi

  # 无 .git 或仍不可用：备份 .env/data 后重新 clone
  echo "将备份配置并重新克隆到 ${root}"
  local stamp backup_dir
  stamp="$(date +%Y%m%d-%H%M%S)"
  backup_dir="/root/backups/eth_hedge_sim/heal-${stamp}"
  mkdir -p "${backup_dir}"
  [[ -f "${root}/.env" ]] && cp -a "${root}/.env" "${backup_dir}/.env"
  [[ -d "${root}/backend/data" ]] && cp -a "${root}/backend/data" "${backup_dir}/data" || true
  echo "备份目录: ${backup_dir}"

  local removed="${root}.old.${stamp}"
  mv "${root}" "${removed}"
  echo "旧目录已移至: ${removed}"
  mkdir -p "$(dirname "${root}")"
  git clone -b "${GIT_BRANCH}" "${GIT_URL}" "${root}"
  if [[ -f "${backup_dir}/.env" ]]; then
    cp -a "${backup_dir}/.env" "${root}/.env"
    echo "已恢复 .env"
  fi
  if [[ -d "${backup_dir}/data" ]]; then
    mkdir -p "${root}/backend"
    cp -a "${backup_dir}/data" "${root}/backend/data"
    echo "已恢复 backend/data"
  fi
  exec bash "${root}/deploy/manage.sh" "$@" </dev/tty
}

bootstrap_repo() {
  if repo_ready "${INSTALL_ROOT}"; then
    REPO_ROOT="${INSTALL_ROOT}"
    DEPLOY_DIR="${REPO_ROOT}/deploy"
    LIB_DIR="${DEPLOY_DIR}/lib"
    sync_repo_if_present "${REPO_ROOT}"
    # pull 后可能才有 lib，再校验一次
    if ! repo_ready "${REPO_ROOT}"; then
      heal_existing_install "${INSTALL_ROOT}" "$@"
    fi
    return 0
  fi
  if [[ -n "${REPO_ROOT}" ]] && repo_ready "${REPO_ROOT}"; then
    DEPLOY_DIR="${REPO_ROOT}/deploy"
    LIB_DIR="${DEPLOY_DIR}/lib"
    return 0
  fi

  # 目录在，但还是旧版（你当前的情况）
  if [[ -d "${INSTALL_ROOT}" ]]; then
    if [[ "$(id -u)" -ne 0 ]]; then
      echo "错误: 请使用 root 执行" >&2
      exit 1
    fi
    heal_existing_install "${INSTALL_ROOT}" "$@"
  fi

  echo "比特骆驼自动化对冲系统 部署管理器 — 首次自举"
  echo "将克隆到: ${INSTALL_ROOT}"
  if [[ "$(id -u)" -ne 0 ]]; then
    echo "错误: 请使用 root 执行" >&2
    exit 1
  fi
  ensure_git_cli
  mkdir -p "$(dirname "${INSTALL_ROOT}")"
  git clone -b "${GIT_BRANCH}" "${GIT_URL}" "${INSTALL_ROOT}"
  # clone 后用仓库内脚本 + 终端 stdin(管道已 EOF)
  exec bash "${INSTALL_ROOT}/deploy/manage.sh" "$@" </dev/tty
}

show_banner() {
  local path
  path="${INSTALL_ROOT}"
  if [[ -n "${REPO_ROOT}" ]] && repo_ready "${REPO_ROOT}"; then
    path="${REPO_ROOT}"
  fi
  echo ""
  echo "╔══════════════════════════════════════╗"
  echo "║   比特骆驼自动化对冲系统 部署管理器   ║"
  echo "║   路径: ${path}"
  echo "╚══════════════════════════════════════╝"
  echo ""
}

show_menu() {
  echo "  1) 一键部署策略机（可选槽位 1/2/3）"
  echo "  2) 一键部署中控机"
  echo "  3) 一键卸载策略机（选槽位）"
  echo "  4) 更新策略机（选槽位 / 全部）"
  echo "  5) 更新中控机"
  echo "  0) 退出"
  echo ""
  echo "  槽位: 1→:5155  2→:5156  3→:5157（同机最多三套，实盘请只用 1）"
  echo ""
}

# 交互读入（兼容 curl|bash）
cm_read() {
  local __var="$1"
  local __prompt="${2:-}"
  local __line=""
  if [[ -n "${__prompt}" ]]; then
    printf '%s' "${__prompt}" >/dev/tty 2>/dev/null || printf '%s' "${__prompt}"
  fi
  if [[ -r /dev/tty ]]; then
    IFS= read -r __line </dev/tty || true
  else
    IFS= read -r __line || true
  fi
  printf -v "${__var}" '%s' "${__line}"
}

# 中控：依赖已齐 + 仓库在位后跑 control/deploy/update.sh
deploy_control_node() {
  require_root
  if ! REPO_ROOT="$(resolve_repo_root)"; then
    die "未找到安装目录 ${INSTALL_ROOT}，请先执行「1) 一键部署策略机」或完成仓库自举"
  fi
  if [[ ! -f "${REPO_ROOT}/control/deploy/update.sh" ]]; then
    die "缺少 control/deploy/update.sh，请先 git pull 更新仓库"
  fi
  step "一键部署中控机 — 环境检测 (缺则装，有则跳过)"
  ensure_system_deps
  step "部署中控 (git pull + 构建 + pm2 eth-hedge-control)"
  bash "${REPO_ROOT}/control/deploy/update.sh"
  echo ""
  log "中控部署完成 → http://<本机IP>:5160  默认账号 admin / admin123"
}

run_with_slot_env() {
  # 子脚本继承当前槽位变量
  env \
    INSTANCE_SLOT="${INSTANCE_SLOT}" \
    INSTALL_ROOT="${INSTALL_ROOT}" \
    API_PORT="${API_PORT}" \
    PM2_APP_NAME="${PM2_APP_NAME}" \
    SKIP_SLOT_PROMPT=1 \
    EHS_FROM_MANAGE=1 \
    "$@"
}

prompt_update_target() {
  local line=""
  echo ""
  echo "更新目标:"
  echo "  1/2/3) 指定槽位"
  echo "  a) 全部已安装槽位（串行，适合 2G 测机）"
  cm_read line "请选择 [1/2/3/a，默认1]: "
  line="${line:-1}"
  case "${line}" in
    a|A|all|ALL)
      EHS_UPDATE_MODE=all
      ;;
    1|2|3)
      EHS_UPDATE_MODE=one
      resolve_slot "${line}"
      ;;
    *)
      echo "无效选择，使用槽位 1"
      EHS_UPDATE_MODE=one
      resolve_slot 1
      ;;
  esac
}

main_menu() {
  bootstrap_repo
  # shellcheck source=lib/common.sh
  source "${LIB_DIR}/common.sh"
  REPO_ROOT="$(resolve_repo_root || echo "${INSTALL_ROOT}")"

  while true; do
    show_banner
    show_menu
    local choice=""
    cm_read choice "请选择 [0-5]: "
    case "${choice}" in
      1)
        prompt_instance_slot
        run_with_slot_env bash "${LIB_DIR}/install.sh"
        ;;
      2)
        deploy_control_node
        ;;
      3)
        prompt_instance_slot
        run_with_slot_env bash "${LIB_DIR}/uninstall.sh"
        ;;
      4)
        prompt_update_target
        if [[ "${EHS_UPDATE_MODE}" == "all" ]]; then
          env EHS_UPDATE_MODE=all SKIP_SLOT_PROMPT=1 bash "${LIB_DIR}/update.sh"
        else
          run_with_slot_env bash "${LIB_DIR}/update.sh"
        fi
        ;;
      5)
        deploy_control_node
        ;;
      0)
        echo "再见."
        exit 0
        ;;
      *)
        echo "无效选项,请输入 0-5"
        ;;
    esac
    echo ""
    cm_read _ "按 Enter 返回菜单..."
  done
}

main_menu "$@"
