#!/usr/bin/env bash
# ============================================================
# LXYSSH.sh - sshtool（量芯云-LXYSSH-AI运维助手）Linux 后台服务管理脚本
#
# 用法（选项放在子命令前后均可）:
# ./LXYSSH.sh start                  # 后台启动，默认 0.0.0.0:9090
# ./LXYSSH.sh start --port 9000      # 自定义端口
# ./LXYSSH.sh start --host 127.0.0.1 --port 9000   # 只监听本机
# ./LXYSSH.sh restart --port 9000    # 重启
# ./LXYSSH.sh stop                   # 关闭
# ./LXYSSH.sh status                 # 查看运行状态
# ./LXYSSH.sh logs -f                # 跟随查看日志
# ./LXYSSH.sh install --port 9000    # 注册为 systemd 服务（开机自启，需 sudo）
# ./LXYSSH.sh uninstall              # 注销 systemd 服务
#
# 自定义配置（优先级：命令行参数 > 环境变量 > 默认值）:
#   --port 9000            端口（默认 8080），等价于 SSHTOOL_PORT=9000
#   --host 127.0.0.1       监听地址（默认 0.0.0.0，全部网卡），等价于 SSHTOOL_HOST
#   --addr 127.0.0.1:9000  完整监听地址，直接透传给 -addr（优先级最高），等价于 SSHTOOL_ADDR
#   SSHTOOL_BIN            可执行文件路径（默认脚本同级目录 LXYSSH-linux）
#   SSHTOOL_DB             数据库路径（默认脚本同级目录 sshtool.db）
#   SSHTOOL_LOG / SSHTOOL_PIDFILE  日志与 PID 文件路径（默认脚本同级目录）
#   SSHTOOL_MASTER_KEY 等其它环境变量：普通后台模式直接继承；
#                        systemd 模式如需加载，可在本脚本同目录建 sshtool.env
#                        （每行 KEY=VALUE）自动生效
#
# 说明：未 install 时由本脚本用 PID 文件管理（无需 root）；
#       install 注册为 systemd 服务后，start/stop/restart/status/logs
#       自动改由 systemctl 管理。
# ============================================================
set -uo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

BIN="${SSHTOOL_BIN:-$SCRIPT_DIR/LXYSSH-linux}"
PORT="${SSHTOOL_PORT:-9090}"
HOST="${SSHTOOL_HOST:-0.0.0.0}"
ADDR="${SSHTOOL_ADDR:-}"
DB="${SSHTOOL_DB:-$SCRIPT_DIR/sshtool.db}"
LOG="${SSHTOOL_LOG:-$SCRIPT_DIR/sshtool.log}"
PIDFILE="${SSHTOOL_PIDFILE:-$SCRIPT_DIR/sshtool.pid}"

UNIT=/etc/systemd/system/sshtool.service
SERVICE_NAME=sshtool
FOLLOW=0

usage() {
  sed -n '2,24p' "$0"
  exit "${1:-0}"
}

# ---------- 参数解析 ----------
COMMAND=""
declare -a REST_ARGS=()
while [[ $# -gt 0 ]]; do
  case "$1" in
    -p|--port) PORT="${2:?--port 需要端口号}"; shift 2 ;;
    --host)    HOST="${2:?--host 需要监听地址}"; shift 2 ;;
    --addr)    ADDR="${2:?--addr 需要监听地址}"; shift 2 ;;
    -f|--follow) FOLLOW=1; shift ;;
    -h|--help) usage 0 ;;
    start|stop|restart|status|logs|install|uninstall)
      if [[ -n "$COMMAND" ]]; then
        echo "错误: 只能指定一个子命令" >&2
        usage 1
      fi
      COMMAND="$1"; shift ;;
    -*) echo "未知参数: $1" >&2; usage 1 ;;
    *) REST_ARGS+=("$1"); shift ;;
  esac
done

if [[ -z "$COMMAND" ]]; then
  echo "错误: 缺少子命令（start/stop/restart/status/logs/install/uninstall）" >&2
  usage 1
fi

# 组合并校验监听地址
if [[ -z "$ADDR" ]]; then
  if [[ ! "$PORT" =~ ^[0-9]+$ ]] || (( PORT < 1 || PORT > 65535 )); then
    echo "错误: 端口必须为 1-65535 的数字，当前: $PORT" >&2
    exit 1
  fi
  ADDR="$HOST:$PORT"
fi

# ---------- 通用函数 ----------
resolve_bin() {
  if [[ ! -f "$BIN" ]]; then
    echo "错误: 未找到可执行文件: $BIN" >&2
    echo "请设置 SSHTOOL_BIN，或从以下文件中选择:" >&2
    ls -1 "$SCRIPT_DIR"/sshtool-linux-amd64-* 2>/dev/null || echo "  （脚本目录下没有 sshtool-linux-amd64-* 文件）" >&2
    exit 1
  fi
  if [[ ! -x "$BIN" ]]; then
    echo "错误: 可执行文件没有执行权限，请先运行: chmod +x $BIN" >&2
    exit 1
  fi
}

pid_of() {
  cat "$PIDFILE" 2>/dev/null
}

# 判断服务是否在运行：PID 文件存在、进程存活、且确实是 sshtool 进程
is_running() {
  [[ -f "$PIDFILE" ]] || return 1
  local pid
  pid="$(pid_of)" || return 1
  [[ "$pid" =~ ^[0-9]+$ ]] || return 1
  [[ -d "/proc/$pid" ]] || return 1
  if [[ -r "/proc/$pid/cmdline" ]]; then
    tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null | grep -q "sshtool" || return 1
  fi
  return 0
}

has_systemd_unit() {
  [[ -f "$UNIT" ]]
}

use_systemd() {
  has_systemd_unit && command -v systemctl >/dev/null 2>&1
}

print_url() {
  local port="${ADDR##*:}"
  echo "访问端口: ${port}"
  echo "后台地址: /adminlxy"
  if [[ "$ADDR" != "127.0.0.1:"* && "$ADDR" != "localhost:"* && "$ADDR" != "[::1]:"* && "$ADDR" != ":"* ]]; then
    echo "（服务器上公网IP加端口访问）"
  fi
}

# ---------- 普通后台模式（PID 文件） ----------
pid_start() {
  resolve_bin
  if is_running; then
    echo "服务已在运行 (PID $(pid_of))"
    print_url
    return 0
  fi

  mkdir -p "$(dirname "$LOG")" "$(dirname "$PIDFILE")" 2>/dev/null || true

  local pid
  if command -v setsid >/dev/null 2>&1; then
    setsid "$BIN" -addr "$ADDR" -db "$DB" >>"$LOG" 2>&1 &
  else
    nohup "$BIN" -addr "$ADDR" -db "$DB" >>"$LOG" 2>&1 &
  fi
  pid=$!
  echo "$pid" > "$PIDFILE"

  # 等待进程起来，避免启动即崩溃时误报成功
  sleep 1
  if ! is_running; then
    echo "启动失败，最近日志:" >&2
    tail -n 20 "$LOG" 2>/dev/null >&2 || true
    rm -f "$PIDFILE"
    return 1
  fi

  echo "服务已启动 (PID $pid)"
  print_url
  echo "日志文件: $LOG"
}

pid_stop() {
  if ! is_running; then
    echo "服务未在运行"
    rm -f "$PIDFILE"
    return 0
  fi

  local pid
  pid="$(pid_of)"
  echo "正在停止 (PID $pid) ..."
  kill -TERM "$pid" 2>/dev/null || true

  local i
  for i in {1..30}; do
    is_running || break
    sleep 0.5
  done

  if is_running; then
    echo "进程未响应 TERM，强制结束" >&2
    kill -KILL "$pid" 2>/dev/null || true
    sleep 1
  fi

  rm -f "$PIDFILE"
  echo "服务已停止"
}

pid_restart() {
  pid_stop >/dev/null 2>&1 || true
  pid_start
}

pid_status() {
  if is_running; then
    echo "服务运行中 (PID $(pid_of))"
    print_url
    echo "数据库: $DB"
    return 0
  fi
  echo "服务未运行（PID 文件: $PIDFILE）"
  return 1
}

pid_logs() {
  [[ -f "$LOG" ]] || { echo "暂无日志文件: $LOG" >&2; return 1; }
  if (( FOLLOW )); then
    tail -f "$LOG"
  else
    tail -n 50 "$LOG"
  fi
}

# ---------- systemd 模式 ----------
sys_start() {
  systemctl start "$SERVICE_NAME" || {
    echo "启动失败，请检查: systemctl status $SERVICE_NAME" >&2
    return 1
  }
  echo "服务已启动"
  systemctl --no-pager status "$SERVICE_NAME" 2>/dev/null | sed -n '1,4p' || true
  print_url
}

sys_stop() {
  systemctl stop "$SERVICE_NAME"
  echo "服务已停止"
}

sys_restart() {
  systemctl restart "$SERVICE_NAME" || {
    echo "重启失败，请检查: systemctl status $SERVICE_NAME" >&2
    return 1
  }
  echo "服务已重启"
  print_url
}

sys_status() {
  systemctl --no-pager status "$SERVICE_NAME"
}

sys_logs() {
  if (( FOLLOW )); then
    journalctl -u "$SERVICE_NAME" -f
  else
    journalctl -u "$SERVICE_NAME" -n 50 --no-pager
  fi
}

# ---------- 注册 / 注销 systemd 服务 ----------
require_root() {
  if [[ "$(id -u)" -ne 0 ]]; then
    echo "该操作需要 root，请用: sudo $0 $COMMAND" >&2
    exit 1
  fi
}

cmd_install() {
  resolve_bin
  if ! command -v systemctl >/dev/null 2>&1; then
    echo "当前系统没有 systemd（无 systemctl），无法注册服务；请直接用 start/stop/restart 管理" >&2
    exit 1
  fi
  require_root

  # 若普通后台模式正在运行，先停止，避免端口冲突
  if is_running; then
    echo "检测到普通后台模式正在运行，先停止 ..."
    pid_stop
  fi

  local user="${SUDO_USER:-$(id -un)}"
  {
    echo "[Unit]"
    echo "Description=量芯云-LXYSSH-AI运维助手"
    echo "After=network.target"
    echo
    echo "[Service]"
    echo "Type=simple"
    echo "User=$user"
    echo "WorkingDirectory=$SCRIPT_DIR"
    echo "ExecStart=$BIN -addr $ADDR -db $DB"
    echo "Restart=on-failure"
    echo "RestartSec=3"
    if [[ -f "$SCRIPT_DIR/sshtool.env" ]]; then
      echo "EnvironmentFile=$SCRIPT_DIR/sshtool.env"
    fi
    echo
    echo "[Install]"
    echo "WantedBy=multi-user.target"
  } > "$UNIT"

  systemctl daemon-reload
  systemctl enable --now "$SERVICE_NAME"
  echo "已注册为 systemd 服务并启动:"
  print_url
  echo "管理: systemctl status/restart/stop $SERVICE_NAME（或继续使用本脚本）"
  echo "开机自启已启用，注销请运行: sudo $0 uninstall"
}

cmd_uninstall() {
  require_root
  if [[ -f "$UNIT" ]]; then
    systemctl disable --now "$SERVICE_NAME" 2>/dev/null || true
    rm -f "$UNIT"
    systemctl daemon-reload
    echo "已注销 systemd 服务"
  else
    echo "未注册 systemd 服务"
  fi
  # 顺带清理普通后台模式的残留进程
  if is_running; then
    pid_stop
  fi
}

# ---------- 主流程 ----------
case "$COMMAND" in
  start)
    if use_systemd; then sys_start; else pid_start; fi
    ;;
  stop)
    if use_systemd; then sys_stop; else pid_stop; fi
    ;;
  restart)
    if use_systemd; then sys_restart; else pid_restart; fi
    ;;
  status)
    if use_systemd; then sys_status; else pid_status; fi
    ;;
  logs)
    if use_systemd; then sys_logs; else pid_logs; fi
    ;;
  install)
    cmd_install
    ;;
  uninstall)
    cmd_uninstall
    ;;
esac
