#!/usr/bin/env bash
# בדיקות שלב 1: מריץ שרת מקומי עם מסד נתונים זמני ובודק התחברות ואבטחה.
# שימוש: bash tests/smoke.sh
set -u
cd "$(dirname "$0")/.."
ROOT="$PWD"
PORT=8099

# הסקריפט כותב וימחק config/site.local.php. אסור להריץ אותו על שרת אמיתי שיש בו הגדרות.
if [ -e config/site.local.php ]; then
  echo "נמצא config/site.local.php. הבדיקות מיועדות לסביבת פיתוח בלבד ויחליפו אותו, לכן הן לא ירוצו כאן."
  exit 2
fi
TMP="$(mktemp -d)"
JAR="$TMP/jar"
PASS=0; FAIL=0

ok()   { PASS=$((PASS+1)); echo "  ✓ $1"; }
bad()  { FAIL=$((FAIL+1)); echo "  ✗ $1"; }
check() { if [ "$2" = "$3" ]; then ok "$1"; else bad "$1 (קיבלתי '$2', ציפיתי '$3')"; fi; }

# הגדרות מקומיות זמניות: מסד SQLite חדש
cat > config/site.local.php <<PHP
<?php
return [
  'site' => ['base_url' => 'http://127.0.0.1:$PORT'],
  'db'   => ['driver' => 'sqlite', 'sqlite_path' => '$TMP/test.sqlite'],
];
PHP
trap 'kill $SRV 2>/dev/null; rm -f config/site.local.php; rm -rf "$TMP"' EXIT

echo "התקנה:"
ADMIN_PASSWORD='correct-horse-battery' php bin/install.php --email=admin@example.com >/dev/null && ok "install.php רץ" || bad "install.php נכשל"
ADMIN_PASSWORD='short' php bin/install.php --email=other@example.com >/dev/null 2>&1 && bad "סיסמה קצרה התקבלה" || ok "סיסמה קצרה נדחית"

php -S 127.0.0.1:$PORT -t public public/index.php >"$TMP/server.log" 2>&1 &
SRV=$!
for i in $(seq 1 30); do curl -s -o /dev/null "http://127.0.0.1:$PORT/" && break; sleep 0.2; done

B="http://127.0.0.1:$PORT"
code() { curl -s -o /dev/null -w '%{http_code}' "$@"; }
token() { curl -s -c "$JAR" -b "$JAR" "$B/admin/login" | grep -o 'name="_csrf" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"//'; }

echo "דפים וכותרות:"
check "דף הבית 200" "$(code $B/)" "200"
check "דף לא קיים 404" "$(code $B/nope)" "404"
check "לוח בקרה בלי התחברות מפנה (302)" "$(code $B/admin)" "302"
HDR="$(curl -s -D - -o /dev/null "$B/admin/login")"
echo "$HDR" | grep -qi '^content-security-policy:' && ok "CSP קיים" || bad "CSP חסר"
echo "$HDR" | grep -qi '^x-frame-options: DENY' && ok "X-Frame-Options" || bad "X-Frame-Options חסר"
echo "$HDR" | grep -qi '^cache-control: no-store' && ok "no-store בניהול" || bad "no-store חסר"
echo "$HDR" | grep -qi '^x-powered-by' && bad "X-Powered-By נחשף" || ok "X-Powered-By מוסתר"

echo "CSRF:"
check "POST בלי אסימון נדחה (419)" "$(code -X POST -d 'email=admin@example.com&password=correct-horse-battery' "$B/admin/login")" "419"
TOK="$(token)"
check "אסימון שגוי נדחה (419)" "$(code -b "$JAR" -X POST -d "_csrf=wrong&email=admin@example.com&password=correct-horse-battery" "$B/admin/login")" "419"
check "Origin זר נדחה (419)" "$(code -b "$JAR" -H 'Origin: http://evil.example' -X POST -d "_csrf=$TOK&email=admin@example.com&password=correct-horse-battery" "$B/admin/login")" "419"

echo "התחברות:"
TOK="$(token)"
check "סיסמה שגויה (401)" "$(code -b "$JAR" -c "$JAR" -X POST -d "_csrf=$TOK&email=admin@example.com&password=wrong-password-123" "$B/admin/login")" "401"
SID_BEFORE="$(grep -o 'sid[[:space:]]*[^[:space:]]*$' "$JAR" | awk '{print $2}')"
TOK="$(token)"
check "סיסמה נכונה מפנה (302)" "$(code -b "$JAR" -c "$JAR" -X POST -d "_csrf=$TOK&email=admin@example.com&password=correct-horse-battery" "$B/admin/login")" "302"
SID_AFTER="$(grep -o 'sid[[:space:]]*[^[:space:]]*$' "$JAR" | awk '{print $2}')"
[ -n "$SID_AFTER" ] && [ "$SID_BEFORE" != "$SID_AFTER" ] && ok "מזהה סשן מתחלף אחרי כניסה" || bad "מזהה הסשן לא התחלף"
check "לוח בקרה אחרי כניסה (200)" "$(code -b "$JAR" "$B/admin")" "200"
curl -s -b "$JAR" "$B/admin" | grep -q 'ממתינות לאישור' && ok "לוח הבקרה מציג נתונים מהמסד" || bad "לוח הבקרה לא הציג נתונים"
grep -q 'HttpOnly' "$JAR" && ok "עוגיית סשן HttpOnly" || bad "העוגייה לא HttpOnly"

echo "התנתקות:"
TOK="$(curl -s -b "$JAR" "$B/admin" | grep -o 'name="_csrf" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"//')"
check "התנתקות בלי אסימון נדחית (419)" "$(code -b "$JAR" -X POST "$B/admin/logout")" "419"
check "התנתקות עם אסימון (302)" "$(code -b "$JAR" -c "$JAR" -X POST -d "_csrf=$TOK" "$B/admin/logout")" "302"
check "אחרי התנתקות הניהול חסום (302)" "$(code -b "$JAR" "$B/admin")" "302"

echo "הזרקות בסיסיות:"
rm -f "$JAR"
TOK="$(token)"
check "SQL injection בשדה האימייל לא נכנס (401)" "$(code -b "$JAR" -c "$JAR" -X POST --data-urlencode "_csrf=$TOK" --data-urlencode "email=' OR 1=1 --" --data-urlencode "password=x" "$B/admin/login")" "401"
TOK="$(token)"
check "SQL injection בשדה הסיסמה לא נכנס (401)" "$(code -b "$JAR" -c "$JAR" -X POST --data-urlencode "_csrf=$TOK" --data-urlencode "email=admin@example.com" --data-urlencode "password=' OR '1'='1" "$B/admin/login")" "401"
check "נתיב עם null byte (400)" "$(code "$B/%00")" "400"
curl -s "$B/admin/login" | grep -q "<script" && bad "יש תגית script בדף הכניסה" || ok "אין סקריפטים בדף הכניסה"

echo "הגבלת ניסיונות:"
rm -f "$JAR"
for i in 1 2 3 4 5; do
  TOK="$(token)"
  code -b "$JAR" -c "$JAR" -X POST -d "_csrf=$TOK&email=victim@example.com&password=bad-guess-$i" "$B/admin/login" >/dev/null
done
TOK="$(token)"
check "אחרי 5 ניסיונות נחסם (429)" "$(code -b "$JAR" -c "$JAR" -X POST -d "_csrf=$TOK&email=admin@example.com&password=correct-horse-battery" "$B/admin/login")" "429"

echo
echo "עברו: $PASS, נכשלו: $FAIL"
[ "$FAIL" -eq 0 ]
