#!/usr/bin/env bash
# 宿主机连接守护：ADB + WS Agent 常驻保活（处理长任务时也不断链）
# 用法:
#   bash sdk/scripts/connection_keeper_daemon.sh          # 前台
#   bash sdk/scripts/connection_keeper_daemon.sh --bg     # 后台
#   bash sdk/scripts/connection_keeper_daemon.sh --once   # 只跑一轮稳定化
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SDK_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
LAN_ENV="${SDK_ROOT}/config/lan.env"
REQUESTED_ADB_PORT="${ANDROID_ADB_SERVER_PORT:-}"
[[ -f "${LAN_ENV}" ]] && source "${LAN_ENV}" || true
[[ -n "${REQUESTED_ADB_PORT}" ]] && export ANDROID_ADB_SERVER_PORT="${REQUESTED_ADB_PORT}"
SDK_PORT="${WORKPHONE_SDK_PORT:-8899}"
INTERVAL="${KEEPER_INTERVAL:-15}"
FAST_INTERVAL="${KEEPER_FAST_INTERVAL:-8}"
DEVICE_SERIAL="${DEVICE_SERIAL:-}"
DEVICE_ID="${DEVICE_ID:-xgfe65eimrrofyws}"
export ANDROID_ADB_SERVER_PORT="${ANDROID_ADB_SERVER_PORT:-5037}"
ADB=(adb -P "${ANDROID_ADB_SERVER_PORT}")
LOG="${SDK_ROOT}/logs/connection_keeper.log"
PID_FILE="${SDK_ROOT}/logs/connection_keeper.pid"

mkdir -p "${SDK_ROOT}/logs"

log() { echo "[$(date '+%F %T')] $*" | tee -a "$LOG"; }

is_phone_serial() {
  local s="$1"
  local brand
  brand=$("${ADB[@]}" -s "$s" shell getprop ro.product.brand 2>/dev/null | tr -d '\r')
  [[ "$brand" != "haier" ]]
}

pick_serial() {
  if [[ -n "$DEVICE_SERIAL" ]]; then
    if "${ADB[@]}" -s "$DEVICE_SERIAL" get-state 2>/dev/null | grep -qx device && is_phone_serial "$DEVICE_SERIAL"; then
      echo "$DEVICE_SERIAL"
      return
    fi
  fi
  local s
  while IFS= read -r s; do
    [[ -z "$s" ]] && continue
    is_phone_serial "$s" || continue
    echo "$s"
    return
  done < <("${ADB[@]}" devices 2>/dev/null | awk '/\tdevice$/{print $1}')
}

usb_xiaomi_present() {
  ioreg -p IOUSB -l 2>/dev/null | grep -q "Xiaomi" 2>/dev/null
}

try_wireless_ports() {
  local host="${1:-192.168.1.12}"
  if usb_xiaomi_present; then
    log "USB Xiaomi detected → skip wireless port scan (优先等 MTP/授权)"
    return 1
  fi
  ping -c 1 -W 2 "$host" >/dev/null 2>&1 || return 1
  "${ADB[@]}" reconnect offline >/dev/null 2>&1 || true
  local p open_port="" hits=0
  for p in 5555 $(seq 37000 37005); do
    if nc -z -G 1 "$host" "$p" 2>/dev/null; then
      hits=$((hits + 1))
      [[ "$hits" -gt 3 ]] && break
      log "wireless port open ${host}:${p} → adb connect"
      ( "${ADB[@]}" connect "${host}:${p}" & pid=$!; sleep 3; kill $pid 2>/dev/null; wait $pid 2>/dev/null ) || true
      if "${ADB[@]}" -s "${host}:${p}" get-state 2>/dev/null | grep -qx device; then
        DEVICE_SERIAL="${host}:${p}"
        echo "$DEVICE_SERIAL"
        return 0
      fi
      "${ADB[@]}" disconnect "${host}:${p}" >/dev/null 2>&1 || true
    fi
  done
  return 1
}

ws_online_count() {
  curl -s "http://127.0.0.1:${SDK_PORT}/api/v3/connection/status" 2>/dev/null | \
    python3 -c "import sys,json;d=json.load(sys.stdin).get('data',{});print(d.get('online_ws_count',0))" 2>/dev/null || echo 0
}

u2_online() {
  curl -s "http://127.0.0.1:${SDK_PORT}/api/v3/devices/${DEVICE_ID}" 2>/dev/null | \
    python3 -c "import sys,json;d=json.load(sys.stdin).get('data',{});print('1' if d.get('quick_status',{}).get('u2') else '0')" 2>/dev/null || echo 0
}

ensure_adb_server() {
  if nc -z 127.0.0.1 "${ANDROID_ADB_SERVER_PORT}" 2>/dev/null; then
    return 0
  fi
  "${ADB[@]}" start-server 2>/dev/null || true
  sleep 1
}

adb_devices_safe() {
  ( "${ADB[@]}" devices "$@" & pid=$!; sleep 8; kill "$pid" 2>/dev/null; wait "$pid" 2>/dev/null ) 2>/dev/null || true
}

keeper_once() {
  ensure_adb_server

  ws="$(ws_online_count)"
  u2_ok="$(u2_online)"
  if [[ "$ws" -ge 1 && "$u2_ok" == "1" ]]; then
    log "ok ws_online=${ws} u2=1"
    return 0
  fi
  if [[ "$ws" -ge 1 ]]; then
    log "ws_online=${ws} but u2=${u2_ok} → continue adb/u2 recovery"
  fi

  serial="$(pick_serial || true)"
  if [[ -z "$serial" ]]; then
    if usb_xiaomi_present; then
      log "USB 已插入但未 adb device → 请在手机选「传输文件」并允许 USB 调试；或开启无线调试"
      # USB 未授权时仍尝试无线 ADB（与 USB 并行）
      for ip in ${WIRELESS_IPS:-192.168.110.80 192.168.3.1}; do
        if serial="$(try_wireless_ports "$ip" || true)" && [[ -n "$serial" ]]; then
          log "wireless adb ok ${serial}"
          break
        fi
      done
      serial="$(pick_serial || true)"
    else
      for ip in ${WIRELESS_IPS:-192.168.110.80 192.168.110.60 192.168.110.197 192.168.3.1 192.168.1.12}; do
        if serial="$(try_wireless_ports "$ip" || true)" && [[ -n "$serial" ]]; then
          break
        fi
        ( "${ADB[@]}" connect "${ip}:5555" & pid=$!; sleep 3; kill "$pid" 2>/dev/null; wait "$pid" 2>/dev/null ) || true
      done
      serial="$(pick_serial || true)"
    fi
  fi

  if [[ -z "$serial" ]]; then
    log "no adb device — 若手机 Termux Agent 已配置 NAS/frp 寻服，可忽略；否则 USB 授权一次做 OTA"
    bash "${SCRIPT_DIR}/sdk_connection_watcher.sh" --once >>"$LOG" 2>&1 || true
    ws="$(ws_online_count)"
    [[ "$ws" -ge 1 ]] && log "sdk_watcher recovered ws=${ws}" && return 0
    return 1
  fi

  state="$("${ADB[@]}" -s "$serial" get-state 2>/dev/null || echo offline)"
  if [[ "$state" == "unauthorized" ]]; then
    log "adb unauthorized serial=${serial} → 请在手机点「允许 USB 调试」"
    return 1
  fi
  if [[ "$state" != "device" ]]; then
    log "adb not ready serial=${serial} state=${state}"
    return 1
  fi

  ws="$(ws_online_count)"
  if [[ "$ws" -ge 1 ]]; then
    log "ok serial=${serial} ws_online=${ws}"
    return 0
  fi

  log "adb ok but ws=0 → termux/on-device agent serial=${serial}"
  DEVICE_SERIAL="$serial" DEVICE_ID="${DEVICE_ID:-xgfe65eimrrofyws}" \
    bash "${SCRIPT_DIR}/termux_push_and_start_agent.sh" >>"$LOG" 2>&1 || true
  ws="$(ws_online_count)"
  if [[ "$ws" -ge 1 ]]; then
    log "termux/oneclick ok ws_online=${ws}"
    return 0
  fi
  log "still ws=0 after termux_push"
  return 1
}

keeper_loop() {
  log "connection_keeper start interval=${INTERVAL}s fast=${FAST_INTERVAL}s port=${SDK_PORT} lan=${WORKPHONE_LAN_IP:-auto}"
  while true; do
    if keeper_once; then
      sleep "$INTERVAL"
    else
      sleep "$FAST_INTERVAL"
    fi
  done
}

case "${1:-}" in
  --once)
    keeper_once
    ;;
  --bg)
    if [[ -f "$PID_FILE" ]] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
      echo "已在运行 PID $(cat "$PID_FILE")"
      exit 0
    fi
    nohup bash "$0" >>"$LOG" 2>&1 &
    echo $! >"$PID_FILE"
    echo "connection_keeper 后台 PID $(cat "$PID_FILE") log=$LOG"
    ;;
  --stop)
    if [[ -f "$PID_FILE" ]]; then
      kill "$(cat "$PID_FILE")" 2>/dev/null || true
      rm -f "$PID_FILE"
      echo "已停止"
    fi
    ;;
  *)
    keeper_loop
    ;;
esac
