#!/bin/bash
# Ydisks 闲鱼助手 — 飞牛 fnOS 原生启停（Go 二进制，无 Docker）
set -u

LOG_FILE="${TRIM_PKGVAR}/logs/server.log"
PID_FILE="${TRIM_PKGVAR}/app.pid"
APP_DIR="${TRIM_APPDEST}"
SERVER="${APP_DIR}/bin/xianyu-server"
BROWSER_INSTALL="${APP_DIR}/bin/browser-install"
RUNTIME_ROOT="${APP_DIR}/playwright-runtime"
KEY_FILE="${TRIM_PKGETC}/data-key"
SETTINGS_CONF="${TRIM_PKGETC}/settings.conf"
ADMIN_BOOTSTRAP_REV_FILE="${TRIM_PKGETC}/admin-bootstrap-rev"
# 飞牛包固定初始/重置管理员密码。拉高 ADMIN_BOOTSTRAP_REV 可在升级后强制改回此密码一次。
DEFAULT_ADMIN_PASSWORD="3dmn.cn"
ADMIN_BOOTSTRAP_REV="2"
DEFAULT_PORT=59188

fail_ui() {
  local msg="$1"
  if [ -n "${TRIM_TEMP_LOGFILE:-}" ]; then
    echo "$msg" >"$TRIM_TEMP_LOGFILE"
  fi
  log_msg "ERROR $msg"
}

log_msg() {
  mkdir -p "${TRIM_PKGVAR}/logs" 2>/dev/null || true
  echo "$(date '+%Y-%m-%d %H:%M:%S') - $*" >>"$LOG_FILE" 2>/dev/null || true
}

normalize_port() {
  local p="${1:-}"
  case "$p" in
    ''|*[!0-9]*) echo "" ; return ;;
  esac
  if [ "$p" -lt 1 ] || [ "$p" -gt 65535 ]; then
    echo ""
    return
  fi
  echo "$p"
}

# 端口优先级：当前向导 wizard_port > settings.conf > TRIM_SERVICE_PORT > 默认
resolve_port() {
  local wizard_from_conf="" port_from_settings="" p=""
  if [ -f "$SETTINGS_CONF" ]; then
    wizard_from_conf="$(grep -E '^wizard_port=' "$SETTINGS_CONF" 2>/dev/null | tail -1 | cut -d= -f2- | tr -d '[:space:]"'"'"'')"
    port_from_settings="$(grep -E '^PORT=' "$SETTINGS_CONF" 2>/dev/null | tail -1 | cut -d= -f2- | tr -d '[:space:]"'"'"'')"
  fi
  p="$(normalize_port "${wizard_port:-}")"
  [ -n "$p" ] || p="$(normalize_port "$wizard_from_conf")"
  [ -n "$p" ] || p="$(normalize_port "$port_from_settings")"
  [ -n "$p" ] || p="$(normalize_port "${TRIM_SERVICE_PORT:-}")"
  [ -n "$p" ] || p="$DEFAULT_PORT"
  PORT="$p"
}

runtime_arch() {
  case "$(uname -m)" in
    aarch64|arm64) echo arm64 ;;
    *) echo amd64 ;;
  esac
}

ensure_runtime() {
  local arch="$1"
  local driver="$RUNTIME_ROOT/$arch/playwright-driver"
  local browsers="$RUNTIME_ROOT/$arch/playwright-browsers"
  if [ -d "$driver" ] && [ -d "$browsers" ] && [ -n "$(ls -A "$browsers" 2>/dev/null || true)" ]; then
    return 0
  fi
  if [ ! -x "$BROWSER_INSTALL" ]; then
    fail_ui "缺少 browser-install，安装包不完整"
    return 1
  fi
  mkdir -p "$driver" "$browsers"
  log_msg "Downloading Chromium runtime ($arch)..."
  if ! "$BROWSER_INSTALL" -driver-dir "$driver" -browser-dir "$browsers" >>"$LOG_FILE" 2>&1; then
    fail_ui "Chromium 下载失败，请检查 NAS 外网后重试启用。日志: $LOG_FILE"
    return 1
  fi
  return 0
}

check_process() {
  local pid="$1"
  [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null
}

status_app() {
  if [ -f "$PID_FILE" ]; then
    local pid
    pid="$(head -n 1 "$PID_FILE" | tr -d '[:space:]')"
    if check_process "$pid"; then
      return 0
    fi
    rm -f "$PID_FILE"
  fi
  return 1
}

# 必要时强制重置 admin 密码（覆盖旧库里已存在的管理员）
bootstrap_admin_password() {
  local admin_password="$1"
  local current_rev=""
  [ -f "$ADMIN_BOOTSTRAP_REV_FILE" ] && current_rev="$(tr -d '[:space:]' <"$ADMIN_BOOTSTRAP_REV_FILE")"
  if [ "$current_rev" = "$ADMIN_BOOTSTRAP_REV" ]; then
    return 0
  fi
  log_msg "Resetting admin password (bootstrap rev $ADMIN_BOOTSTRAP_REV)..."
  if ! "$SERVER" \
    -workdir "${TRIM_PKGVAR}" \
    -playwright-runtime-root "$RUNTIME_ROOT" \
    -data-key-file "$KEY_FILE" \
    -init-admin \
    -admin-password "$admin_password" \
    -log-format json \
    >>"$LOG_FILE" 2>&1; then
    fail_ui "重置管理员密码失败，见日志: $LOG_FILE"
    return 1
  fi
  printf '%s' "$ADMIN_BOOTSTRAP_REV" >"$ADMIN_BOOTSTRAP_REV_FILE"
  chmod 600 "$ADMIN_BOOTSTRAP_REV_FILE" || true
  log_msg "Admin password reset OK"
  return 0
}

start_app() {
  resolve_port
  mkdir -p "${TRIM_PKGVAR}/data" "${TRIM_PKGVAR}/logs" "${TRIM_PKGETC}" 2>/dev/null || true
  if [ ! -x "$SERVER" ]; then
    fail_ui "缺少程序: $SERVER（请安装对应架构的 .fpk）"
    exit 1
  fi
  if [ ! -s "$KEY_FILE" ]; then
    fail_ui "缺少 data-key，请重新安装本应用"
    exit 1
  fi
  local admin_password="${XIANYU_ADMIN_PASSWORD:-$DEFAULT_ADMIN_PASSWORD}"
  if status_app; then
    return 0
  fi
  local arch
  arch="$(runtime_arch)"
  if ! ensure_runtime "$arch"; then
    exit 1
  fi
  if ! bootstrap_admin_password "$admin_password"; then
    exit 1
  fi

  log_msg "Starting Ydisks on :$PORT workdir=${TRIM_PKGVAR}"
  rm -f "$PID_FILE"
  nohup "$SERVER" \
    -addr "0.0.0.0:${PORT}" \
    -workdir "${TRIM_PKGVAR}" \
    -playwright-runtime-root "$RUNTIME_ROOT" \
    -data-key-file "$KEY_FILE" \
    -ensure-admin \
    -admin-password "$admin_password" \
    -log-format json \
    >>"$LOG_FILE" 2>&1 &
  echo "$!" >"$PID_FILE"

  local i
  for i in 1 2 3 4 5 6 7 8 9 10; do
    sleep 1
    if status_app; then
      log_msg "Started OK pid=$(head -n 1 "$PID_FILE" | tr -d '[:space:]') port=$PORT"
      return 0
    fi
  done

  {
    echo "进程启动后退出。常见原因：端口 ${PORT} 被占用、数据目录无写权限、Chromium 未就绪。"
    echo "日志: $LOG_FILE"
    tail -n 40 "$LOG_FILE" 2>/dev/null || true
  } >"${TRIM_TEMP_LOGFILE:-/dev/null}"
  log_msg "ERROR process exited after start"
  exit 1
}

stop_app() {
  resolve_port
  log_msg "Stopping Ydisks..."
  if [ ! -f "$PID_FILE" ]; then
    return 0
  fi
  local pid
  pid="$(head -n 1 "$PID_FILE" | tr -d '[:space:]')"
  if [ -z "$pid" ] || ! check_process "$pid"; then
    rm -f "$PID_FILE"
    return 0
  fi
  kill -TERM "$pid" 2>>"$LOG_FILE" || true
  local count=0
  while check_process "$pid" && [ "$count" -lt 15 ]; do
    sleep 1
    count=$((count + 1))
  done
  if check_process "$pid"; then
    kill -KILL "$pid" 2>>"$LOG_FILE" || true
  fi
  rm -f "$PID_FILE"
}

resolve_port
case "${1:-}" in
  start) start_app; exit 0 ;;
  stop) stop_app; exit 0 ;;
  status)
    if status_app; then exit 0; fi
    exit 3
    ;;
  *)
    echo "Unknown command: ${1:-}" >"${TRIM_TEMP_LOGFILE:-/dev/null}"
    exit 1
    ;;
esac
