#!/usr/bin/env bash
# نگهبان ربات (v2.1.5): اگه پردازه‌ی PHP بمیره دوباره بالا می‌آرودش.
#  • فقط یک نگهبان هم‌زمان اجرا می‌شود (قفل)، تا چند نگهبان هم را نکشند.
#  • ضربان قلب (bot-heartbeat.txt) فقط وقتی «قفل‌شدن» حساب می‌شود که ربات بیش از ۱۰ دقیقه ضربان ندهد؛ اول SIGTERM، بعد SIGKILL.
#  • ضربان کهنه‌ی اجرای قبلی هر بار پیش از شروع پاک می‌شود (قبلاً ربات تازه‌شروع را به‌خاطر آن می‌کشت).
# توقف کامل:  bash run.sh stop
cd "$(dirname "$0")" || exit 1
exec 9>traderpro-supervisor.lock
flock -n 9 || { echo "[$(date '+%F %T')] supervisor: another supervisor is already running; exiting" >> traderpro.out; exit 0; }
# v2.4.9 — فقط php از نوع CLI؛ در کرون PATH فرق دارد و «php» ممکن است cgi/fcgi باشد (STDOUT تعریف نبود و ربات کرش می‌کرد)
pick_php() {
    local c p
    for c in "$1" php /usr/local/bin/php /usr/bin/php /opt/cpanel/ea-php*/root/usr/bin/php /opt/alt/php*/usr/bin/php; do
        [ -n "$c" ] || continue
        p="$(command -v "$c" 2>/dev/null)" || continue
        [ "$("$p" -r 'echo PHP_SAPI;' 2>/dev/null)" = "cli" ] && { echo "$p"; return 0; }
    done
    command -v "$1" 2>/dev/null || echo "$1"
}
PHP_BIN="$(pick_php "${PHP_BIN:-php}")"
HB="bot-heartbeat.txt"
HUNG_AFTER=600      # ثانیه بدون ضربان
fast_crashes=0
while true; do
    # v2.4.4: traderpro.out هیچ‌وقت نباید بی‌نهایت بزرگ شود (دیسک پر = خاموشی)
    [ -f traderpro.out ] && [ "$(stat -c %s traderpro.out 2>/dev/null || echo 0)" -gt 5242880 ] && tail -c 1048576 traderpro.out > traderpro.out.tmp && mv -f traderpro.out.tmp traderpro.out
    rm -f "$HB"
    started=$(date +%s)
    echo "[$(date '+%F %T')] supervisor: starting bot" >> traderpro.out
    "$PHP_BIN" traderpro.php >> traderpro.out 2>&1 9>&- &
    pid=$!
    while kill -0 "$pid" 2>/dev/null; do
        sleep 20
        now=$(date +%s)
        if [ -f "$HB" ]; then last=$(cat "$HB" 2>/dev/null || echo 0); else last=$started; fi
        age=$(( now - last ))
        if [ "$age" -gt "$HUNG_AFTER" ] && [ $(( now - started )) -gt "$HUNG_AFTER" ]; then
            echo "[$(date '+%F %T')] supervisor: no heartbeat for ${age}s, restarting hung bot" >> traderpro.out
            kill -TERM "$pid" 2>/dev/null; sleep 10; kill -9 "$pid" 2>/dev/null
        fi
    done
    wait "$pid" 2>/dev/null; code=$?
    ran=$(( $(date +%s) - started ))
    note=""
    [ "$code" -eq 137 ] && note=" (SIGKILL: کشته شدن توسط هاست/کمبود حافظه یا نگهبان)"
    [ "$code" -eq 1 ] && [ "$ran" -lt 10 ] && note=" (احتمالاً نمونه‌ی دیگری از ربات در حال اجراست)"
    echo "[$(date '+%F %T')] supervisor: bot exited (code $code) after ${ran}s$note" >> traderpro.out
    if [ "$ran" -lt 20 ]; then fast_crashes=$((fast_crashes+1)); else fast_crashes=0; fi
    if [ "$fast_crashes" -ge 5 ]; then sleep 60; elif [ "$ran" -lt 10 ]; then sleep 10; else sleep 3; fi
done
