#!/usr/bin/env bash
# ────────────────────────────────────────────────────────────────────────────
#  restart_v3_lowpower_debug.sh — variante BAJO CONSUMO **CON VENTANA** (DEBUG)
#
#  Pensada para COMPROBAR VISUALMENTE el arranque cuando algo falla.
#  A diferencia de restart_v3_lowpower.sh, este SÍ muestra la ventana del
#  emulador (NO usa -no-window), para que puedas ver login/captcha/popups de
#  Evony y diagnosticar el fallo de arranque.
#
#  Render por GPU del host (con ventana visible para depurar):
#    -gpu host                 → render por la GPU del host (Metal). NO swiftshader:
#                               swiftshader (CPU) atragantaba la mitad densa (W) y la
#                               congelaba (hilo Unity trabado -> frida create_script
#                               timeout). host = como el restart_v3.sh original.
#    -no-audio                 → sin stack de audio.
#    -no-snapshot-load         → arranque limpio (igual que el original).
#    -no-boot-anim             → sin animación de boot (igual que el original).
#    -no-snapshot-save         → no guarda snapshot al cerrar (arranque siempre limpio).
#    -netdelay none -netspeed full → sin throttling de red emulada.
#
#  Lo que NO lleva (a propósito, para poder VER y depurar):
#    -no-window  → AQUÍ NO. Queremos ver la pantalla.
#
#  Variable LOWPOWER:
#    LOWPOWER=1 (default) → GPU host + flags de bajo consumo (CON ventana).
#    LOWPOWER=0           → arranque como el restart_v3.sh original (GPU host, con ventana).
#
#  Uso:
#    ./restart_v3_lowpower_debug.sh           → restart COMPLETO (debug, con ventana)
#    ./restart_v3_lowpower_debug.sh --fast    → restart solo backend
#    ./restart_v3_lowpower_debug.sh --tail    → restart completo + sigue log
#    ./restart_v3_lowpower_debug.sh --status  → solo diagnostica
#    ./restart_v3_lowpower_debug.sh --stop    → para backend + emuladores
# ────────────────────────────────────────────────────────────────────────────
set -u

V3_DIR=/Users/danicosta/Desktop/Evony/evony-scout-v3-research
PY=/Applications/Xcode.app/Contents/Developer/usr/bin/python3
EMU_BIN=/opt/homebrew/share/android-commandlinetools/emulator/emulator
FS_BIN="$V3_DIR/frida-server-17.9.10-android-arm64"
LOG=/tmp/evony_v3.log
PORT=8772

# ───── BAJO CONSUMO CON VENTANA (DEBUG): flags extra del emulador ─────
# Render al mínimo PERO con ventana visible para depurar el arranque.
# NO incluye -no-window (a propósito).
LOWPOWER="${LOWPOWER:-1}"
if [ "$LOWPOWER" = "1" ]; then
  EMU_EXTRA_FLAGS="-gpu host -no-audio -no-snapshot-save -netdelay none -netspeed full"
else
  EMU_EXTRA_FLAGS=""
fi

# AVDs y puertos (cuentas server #1939)
AVD_W=evony1_1939   ; PORT_W=6000
AVD_E=evony2_1939   ; PORT_E=6002

# ───── helpers ─────
log()  { echo "[$(date +%H:%M:%S)] $*"; }
fail() { echo "[$(date +%H:%M:%S)] [!] $*" >&2; exit 1; }

emu_pid() { lsof -ti :$1 2>/dev/null; }

adb_dev() { adb devices 2>/dev/null | grep -E "^emulator-$1\s+device$"; }

emu_alive() {
  local p=$1
  [ -n "$(emu_pid $p)" ] && [ -n "$(adb_dev $p)" ]
}

ensure_emulator_up() {
  local avd=$1 port=$2
  if [ "${FULL_RESTART:-0}" = "1" ] && emu_alive $port; then
    log "  $avd:$port vivo → kill clean para restart..."
    adb -s emulator-$port emu kill >/dev/null 2>&1
    local i
    for i in $(seq 1 15); do
      if ! emu_alive $port; then break; fi
      sleep 2
    done
    if emu_alive $port; then
      log "  $avd:$port no se cerró limpiamente, force kill..."
      lsof -ti :$port 2>/dev/null | xargs -I{} kill -9 {} 2>/dev/null
      sleep 3
    fi
  fi
  if emu_alive $port; then
    log "  $avd:$port ya vivo"
    return 0
  fi
  if [ "$LOWPOWER" = "1" ]; then
    log "  arrancando $avd en puerto $port (DEBUG low-power: CON ventana + GPU host)..."
  else
    log "  arrancando $avd en puerto $port..."
  fi
  # shellcheck disable=SC2086
  nohup "$EMU_BIN" -avd $avd -port $port -no-snapshot-load -no-boot-anim $EMU_EXTRA_FLAGS \
        >/tmp/evony_$port.log 2>&1 &
  disown
  local i
  for i in $(seq 1 60); do
    local s=$(adb -s emulator-$port shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')
    if [ "$s" = "1" ]; then
      log "  $avd:$port booted en $((i*2))s"
      sleep 3
      return 0
    fi
    sleep 2
  done
  fail "$avd:$port no completó boot en 120s"
}

ensure_magisk_root() {
  local port=$1
  local who=$(adb -s emulator-$port shell "su -c 'whoami'" 2>&1 | tr -d '\r' | head -1)
  if [ "$who" = "root" ]; then
    log "  $port Magisk root OK"
    return 0
  fi
  log "  $port Magisk grant denegado, lanzando app..."
  adb -s emulator-$port shell "monkey -p com.topjohnwu.magisk -c android.intent.category.LAUNCHER 1" \
       >/dev/null 2>&1
  sleep 8
  who=$(adb -s emulator-$port shell "su -c 'whoami'" 2>&1 | tr -d '\r' | head -1)
  if [ "$who" = "root" ]; then
    log "  $port Magisk root tras re-grant OK"
    adb -s emulator-$port shell "su -c 'magisk --sqlite \"INSERT OR REPLACE INTO policies (uid, policy, until, logging, notification) VALUES (2000, 2, 0, 0, 0)\"'" >/dev/null 2>&1
    return 0
  fi
  fail "$port no consigue root via Magisk (su -c falla)"
}

ensure_frida_binary() {
  local port=$1
  local has=$(adb -s emulator-$port shell "ls /data/local/tmp/frida-server 2>/dev/null" | tr -d '\r')
  if [ -n "$has" ]; then
    log "  $port frida-server binary OK"
    return 0
  fi
  log "  $port pushing frida-server..."
  adb -s emulator-$port push "$FS_BIN" /data/local/tmp/frida-server >/dev/null 2>&1
  adb -s emulator-$port shell "su -c 'chmod 755 /data/local/tmp/frida-server'" >/dev/null 2>&1
  has=$(adb -s emulator-$port shell "ls /data/local/tmp/frida-server 2>/dev/null" | tr -d '\r')
  [ -n "$has" ] || fail "$port no consigue pushear frida-server"
  log "  $port frida-server pushed"
}

ensure_frida_running() {
  local port=$1
  local listen=$(adb -s emulator-$port shell "su -c 'netstat -anl 2>/dev/null | grep \":27042 \" | grep LISTEN'" 2>&1 | head -1)
  if [ -n "$listen" ] && echo "$listen" | grep -q LISTEN; then
    log "  $port frida-server LISTEN OK"
    return 0
  fi
  log "  $port arrancando frida-server (setsid)..."
  adb -s emulator-$port shell "su -c 'pkill -9 -f /data/local/tmp/frida-server 2>/dev/null'" >/dev/null 2>&1
  sleep 2
  adb -s emulator-$port shell "su -c 'setsid /data/local/tmp/frida-server </dev/null >/dev/null 2>&1 &'" >/dev/null 2>&1
  local i
  for i in $(seq 1 8); do
    sleep 2
    listen=$(adb -s emulator-$port shell "su -c 'netstat -anl 2>/dev/null | grep \":27042 \" | grep LISTEN'" 2>&1 | head -1)
    if [ -n "$listen" ] && echo "$listen" | grep -q LISTEN; then
      log "  $port frida-server LISTEN tras $((i*2))s OK"
      return 0
    fi
  done
  log "  $port retry final tras 16s sin LISTEN..."
  adb -s emulator-$port shell "su -c 'pkill -9 -f /data/local/tmp/frida-server 2>/dev/null'" >/dev/null 2>&1
  sleep 3
  adb -s emulator-$port shell "su -c 'setsid /data/local/tmp/frida-server </dev/null >/dev/null 2>&1 &'" >/dev/null 2>&1
  for i in $(seq 1 6); do
    sleep 2
    listen=$(adb -s emulator-$port shell "su -c 'netstat -anl 2>/dev/null | grep \":27042 \" | grep LISTEN'" 2>&1 | head -1)
    if [ -n "$listen" ] && echo "$listen" | grep -q LISTEN; then
      log "  $port frida-server LISTEN tras retry final ($((i*2))s) OK"
      return 0
    fi
  done
  fail "$port frida-server no LISTEN tras 2 intentos (28s) — revisar Magisk daemon"
}

ensure_evony_running() {
  local port=$1
  if [ "${FULL_RESTART:-0}" = "1" ]; then
    log "  $port [FULL] force-stop Evony para limpiar estado pre-IL2CPP..."
    adb -s emulator-$port shell "am force-stop com.topgamesinc.evony" >/dev/null 2>&1
    sleep 3
    log "  $port [FULL] am start Evony..."
    adb -s emulator-$port shell "am start -n com.topgamesinc.evony/com.topgamesinc.androidplugin.UnityActivity" >/dev/null 2>&1
    log "  $port settle 18s (Unity + IL2CPP load)..."
    sleep 18
    local ev=$(adb -s emulator-$port shell "pidof com.topgamesinc.evony" 2>&1 | tr -d '\r')
    [ -n "$ev" ] || fail "$port Evony no arrancó tras force-stop+restart"
    log "  $port Evony PID=$ev tras settle (full restart)"
    return 0
  fi
  local ev=$(adb -s emulator-$port shell "pidof com.topgamesinc.evony" 2>&1 | tr -d '\r')
  if [ -n "$ev" ]; then
    log "  $port Evony PID=$ev OK (reusing)"
    return 0
  fi
  log "  $port arrancando Evony..."
  adb -s emulator-$port shell "am start -n com.topgamesinc.evony/com.topgamesinc.androidplugin.UnityActivity" >/dev/null 2>&1
  log "  $port settle 25s (esperando Unity init)..."
  sleep 25
  ev=$(adb -s emulator-$port shell "pidof com.topgamesinc.evony" 2>&1 | tr -d '\r')
  [ -n "$ev" ] || fail "$port Evony no arrancó"
  log "  $port Evony PID=$ev tras settle"
}

restart_evony_settled() {
  local port=$1
  log "  $port force-stop + relanzar Evony..."
  adb -s emulator-$port shell "am force-stop com.topgamesinc.evony" >/dev/null 2>&1
  sleep 3
  adb -s emulator-$port shell "am start -n com.topgamesinc.evony/com.topgamesinc.androidplugin.UnityActivity" >/dev/null 2>&1
  log "  $port settle 25s..."
  sleep 25
}

setup_half() {
  local avd=$1 port=$2
  ensure_emulator_up   "$avd" "$port"
  ensure_magisk_root   "$port"
  ensure_frida_binary  "$port"
  ensure_frida_running "$port"
  ensure_evony_running "$port"
}

case "${1:-start}" in
  --status|status)
    log "=== V3 STATUS DIAGNOSTIC (DEBUG, LOWPOWER=$LOWPOWER) ==="
    echo "Backend :$PORT: $(lsof -ti :$PORT 2>/dev/null || echo MUERTO)"
    for cfg in "W:$PORT_W" "E:$PORT_E"; do
      half=${cfg%:*}; p=${cfg#*:}
      ev=$(adb -s emulator-$p shell "pidof com.topgamesinc.evony" 2>/dev/null | tr -d '\r')
      fs=$(adb -s emulator-$p shell "su -c 'netstat -anl 2>/dev/null | grep \":27042 \" | grep LISTEN'" 2>/dev/null | head -1)
      who=$(adb -s emulator-$p shell "su -c 'whoami'" 2>/dev/null | tr -d '\r' | head -1)
      echo "$half (port $p):"
      echo "  adb device: $(adb_dev $p && echo OK || echo NO)"
      echo "  Magisk root: ${who:-DENIED}"
      echo "  frida LISTEN: $([ -n "$fs" ] && echo OK || echo NO)"
      echo "  Evony PID: ${ev:-NOT RUNNING}"
    done
    exit 0
    ;;

  --stop|stop)
    log "=== STOPPING V3 + EMULATORS (clean) ==="
    lsof -ti :$PORT 2>/dev/null | xargs -I{} kill -9 {} 2>/dev/null
    pkill -9 -f "iscout_web.py" 2>/dev/null
    for p in $PORT_W $PORT_E; do
      adb -s emulator-$p emu kill >/dev/null 2>&1
    done
    sleep 4
    log "  todos detenidos"
    exit 0
    ;;

  --tail)      TAIL=1; FULL_RESTART=1 ;;
  --fast)      TAIL=0; FULL_RESTART=0 ;;
  --tail-fast) TAIL=1; FULL_RESTART=0 ;;
  start|"")    TAIL=0; FULL_RESTART=1 ;;
  --help|-h) sed -n '2,40p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
  *) echo "Usage: $0 {start|--fast|--tail|--tail-fast|--status|--stop|--help}"; exit 1 ;;
esac
export FULL_RESTART

if [ "${FULL_RESTART:-0}" = "1" ]; then
  log "=== V3 RESTART · TOTAL · DEBUG low-power (CON ventana) · LOWPOWER=$LOWPOWER ==="
else
  log "=== V3 RESTART · FAST · DEBUG low-power · LOWPOWER=$LOWPOWER ==="
fi

log "[0/8] validar iscout_web.py..."
"$PY" -c "import py_compile; py_compile.compile('$V3_DIR/iscout_web.py', doraise=True)" 2>&1 \
  || fail "iscout_web.py sintaxis rota — abort"
log "  PY OK"

log "[1/8] matar backend viejo..."
lsof -ti :$PORT 2>/dev/null | xargs -I{} kill -9 {} 2>/dev/null
pkill -9 -f "iscout_web.py" 2>/dev/null
sleep 2

log "[2/4] preparando emuladores W+E EN PARALELO (boot+Magisk+frida+Evony)..."
setup_half "$AVD_W" "$PORT_W" & PID_W=$!
setup_half "$AVD_E" "$PORT_E" & PID_E=$!
RC_W=0; RC_E=0
wait "$PID_W" || RC_W=$?
wait "$PID_E" || RC_E=$?
[ "$RC_W" = "0" ] || fail "setup W ($PORT_W) falló (rc=$RC_W) — ver mensajes arriba"
[ "$RC_E" = "0" ] || fail "setup E ($PORT_E) falló (rc=$RC_E) — ver mensajes arriba"
log "  ambos emuladores listos (W+E)"

log "[3/4] arrancar V3 backend..."
> "$LOG"
ISCOUT_BIND="$(tailscale ip -4 2>/dev/null | head -1)"
[ -z "$ISCOUT_BIND" ] && ISCOUT_BIND="127.0.0.1"
export ISCOUT_BIND
log "  bind backend en $ISCOUT_BIND:8772"
cd "$V3_DIR" && nohup "$PY" iscout_web.py >"$LOG" 2>&1 &
disown
for i in $(seq 1 20); do
  [ -n "$(lsof -ti :$PORT 2>/dev/null)" ] && break
  sleep 2
done
[ -n "$(lsof -ti :$PORT 2>/dev/null)" ] || fail "V3 backend no abrió :$PORT tras 40s — ver $LOG"
log "  V3 backend up en http://127.0.0.1:$PORT"

log "[4/4] esperar attach completo (max 90s)..."
DEADLINE=$(($(date +%s) + 90))
W_OK=0; E_OK=0
while [ "$(date +%s)" -lt "$DEADLINE" ]; do
  [ "$W_OK" = "0" ] && grep -q "\[W self\] uid=" "$LOG" 2>/dev/null && { W_OK=1; log "  W self uid detected"; }
  [ "$E_OK" = "0" ] && grep -q "\[E self\] uid=" "$LOG" 2>/dev/null && { E_OK=1; log "  E self uid detected"; }
  [ "$W_OK" = "1" ] && [ "$E_OK" = "1" ] && break
  if [ "$W_OK" = "0" ] && [ $(grep -c "\[W\] error: unexpectedly timed out" "$LOG") -ge 3 ]; then
    log "  [retry] W attach repeats fails -> restart Evony 6000 con settle"
    restart_evony_settled $PORT_W
    sed -i.bak '/\[W\] error: unexpectedly timed out/d' "$LOG" 2>/dev/null
  fi
  if [ "$E_OK" = "0" ] && [ $(grep -c "\[E\] error: unexpectedly timed out" "$LOG") -ge 3 ]; then
    log "  [retry] E attach repeats fails -> restart Evony 6002 con settle"
    restart_evony_settled $PORT_E
    sed -i.bak '/\[E\] error: unexpectedly timed out/d' "$LOG" 2>/dev/null
  fi
  sleep 3
done

if [ "$W_OK" = "1" ] && [ "$E_OK" = "1" ]; then
  log "=== ✅ V3 listo y operativo (DEBUG, LOWPOWER=$LOWPOWER) ==="
  log "  W uid: $(grep '\[W self\] uid=' $LOG | tail -1 | sed 's/.*uid=//')"
  log "  E uid: $(grep '\[E self\] uid=' $LOG | tail -1 | sed 's/.*uid=//')"
  log "  Server: $(grep 'server_id\]' $LOG | tail -1 | sed 's/.*\] //; s/ (.*//')"
  log "  UI: http://127.0.0.1:$PORT"
else
  log "[!] timeout esperando attach completo (W=$W_OK E=$E_OK). Revisa $LOG"
fi

[ "$TAIL" = "1" ] && { log "tailing $LOG..."; exec tail -f "$LOG"; }
exit 0   # sin --tail, el test anterior devuelve 1; forzamos 0 (el restart fue OK)
