#!/usr/bin/env bash

# 配置部分
BASE_PATH=/data/project_ks/shz-backend
DES_PATH=/data/project_ks/shz-backend
JAR_PATH=${DES_PATH}/ruoyi-admin/target/ruoyi-admin.jar
LOG_PATH=${DES_PATH}/logs
LOG_FILE=${LOG_PATH}/backend.log
BACK_LOG=${LOG_PATH}/back/backend-info.log
MODEL_NAME=${JAR_PATH}
PROFILE=dev

# JVM配置
JVM_MEMORY=" -Xms2048M -Xmx2048M -XX:MaxDirectMemorySize=2048M"
# 远程调试
JVM_DEBUG=""
# JVM_DEBUG=" -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=6011"
JVM_OPTION="${JVM_MEMORY} ${JVM_DEBUG}"

_math() {
  printf "%s" "$(($@))"
}

# 输出绿色文字
__green() {
    printf '\33[1;32m%b\33[0m' "$1" "\n"
}

# 输出红色文字
__red() {
    printf '\33[1;31m%b\33[0m' "$1" "\n"
}

__kill() {
  local jar_path="$1"
  local sleep_seconds=10
  local cur_sleep_second=1
  local pids=()

  # 使用临时文件或直接遍历 jps 输出（避免进程替换）
  jps -l 2>/dev/null | while read -r pid main_class; do
    if [ "$main_class" = "$jar_path" ]; then
      echo "$pid"
    fi
  done > /tmp/ruoyi_pids.$$

  # 读取匹配的 PID 到数组（在当前 shell 中）
  while IFS= read -r pid; do
    [ -n "$pid" ] && pids+=("$pid")
  done < /tmp/ruoyi_pids.$$

  # 清理临时文件
  rm -f /tmp/ruoyi_pids.$$

  if [ ${#pids[@]} -eq 0 ]; then
    __green "未找到运行中的进程: $jar_path"
    return 0
  fi

  __green "找到 ${#pids[@]} 个匹配进程: ${pids[*]}"

  # 发送 SIGTERM
  for pid in "${pids[@]}"; do
    __green "发送 SIGTERM 到 PID: $pid"
    kill "$pid" >/dev/null 2>&1
  done

  # 等待退出
  while [ $cur_sleep_second -le $sleep_seconds ]; do
    remaining=()
    for pid in "${pids[@]}"; do
      if kill -0 "$pid" 2>/dev/null; then
        remaining+=("$pid")
      fi
    done

    if [ ${#remaining[@]} -eq 0 ]; then
      __green "所有进程已成功停止"
      return 0
    fi

    __green "等待进程退出... (${cur_sleep_second}/${sleep_seconds} 秒)"
    sleep 1
    cur_sleep_second=$((cur_sleep_second + 1))
  done

  # 强制 kill -9
  __red "优雅关闭超时，强制终止剩余进程: ${remaining[*]}"
  for pid in "${remaining[@]}"; do
    kill -9 "$pid" 2>/dev/null
  done

  # 检查是否还有存活
  still_alive=()
  for pid in "${remaining[@]}"; do
    if kill -0 "$pid" 2>/dev/null; then
      still_alive+=("$pid")
    fi
  done

  if [ ${#still_alive[@]} -gt 0 ]; then
    __red "无法终止进程: ${still_alive[*]}"
    return 1
  else
    __green "所有进程已强制终止"
    return 0
  fi
}

# 获取本机IP
__get_ip() {
  local ip=$(ifconfig | grep "10.0.0" | awk '{print $2}' | cut -d ':' -f 2 | head -n 1)
  if [[ -z "$ip" ]]; then
    ip=$(ifconfig -a | grep -E '172.|10.|192.' | grep -E 'Bcast|broadcast' | grep -E 'Mask|netmask' | awk '{print $2}' | cut -d ':' -f 2 | head -n 1)
  fi
  echo "$ip"
}

# 创建日志目录
__create_log_dir() {
  if [[ ! -d "$LOG_PATH" ]]; then
    mkdir -p "$LOG_PATH"
    __green "创建日志目录: $LOG_PATH"
  fi

  if [[ ! -d "$(dirname "$BACK_LOG")" ]]; then
    mkdir -p "$(dirname "$BACK_LOG")"
    __green "创建备份日志目录: $(dirname "$BACK_LOG")"
  fi
}

# 主函数
main() {
  # 加载环境变量
  source /etc/profile

  # 获取最新代码
  __green "拉取最新代码..."
  git --git-dir=${BASE_PATH}/.git --work-tree=${BASE_PATH} fetch origin main
  git --git-dir=${BASE_PATH}/.git --work-tree=${BASE_PATH} reset --hard origin/main
  git --git-dir=${BASE_PATH}/.git --work-tree=${BASE_PATH} pull origin main

  # 构建项目
  __green "开始构建项目..."
  cd ${BASE_PATH} && mvn clean && mvn install -T 4

  if [[ $? -ne 0 ]]; then
    __red "Maven构建失败!"
    exit 1
  fi

  # 检查JAR文件是否存在
  if [[ ! -f "$JAR_PATH" ]]; then
    __red "JAR文件不存在: $JAR_PATH"
    exit 1
  fi

  # 停止现有进程
  __green "停止现有进程..."
  __kill "$MODEL_NAME"

  # 创建日志目录
  __create_log_dir

  # 获取本机IP
  SELF_IP=$(__get_ip)
  __green "本机IP: $SELF_IP"

  # 启动应用
  __green "启动应用..."
  nohup java ${JVM_OPTION} -jar ${JAR_PATH} --spring.profiles.active=${PROFILE} >> ${LOG_FILE} 2>&1 &
  tail -f logs/backend.log
  # 等待应用启动
  sleep 3

  # 检查进程是否启动成功
  local new_pid=$(ps -ef | grep "${MODEL_NAME}.jar" | grep -v grep | awk '{print $2}')
  if [[ -n "$new_pid" ]]; then
    __green "应用启动成功! PID: $new_pid"
  else
    __red "应用启动失败!"
    exit 1
  fi

  # 跟踪日志
  __green "开始跟踪日志..."
  tail -f ${LOG_FILE}
}

# 执行主函数
main "$@"