#!/usr/bin/env bash
# ============================================================================
# Overmind Bridge - Smoke Test (post-install validation)
# ============================================================================
#
# Verifie en moins de 10s qu'un bridge nouvellement installe repond
# correctement. A lancer apres "systemctl start overmind-bridge".
#
# Usage:
#   ./scripts/bridge-smoke-test.sh
#   ./scripts/bridge-smoke-test.sh --host 192.168.1.10 --port 3100
#   ./scripts/bridge-smoke-test.sh --auth-token secret
#
# Exit codes:
#   0 = tous les tests OK
#   1 = au moins un test a echoue
#
# Dependances : bash 4+, curl, jq (optionnel)
# ============================================================================

set -uo pipefail

# === Defaults ===
HOST="127.0.0.1"
PORT="3100"
AUTH_TOKEN_VAL=""
ENV_FILE="/etc/overmind/bridge.env"
TIMEOUT=5

# === Couleurs, auto-desactivees si pas TTY ===
if [[ -t 1 ]]; then
  C_RED=$'\033[0;31m'
  C_GREEN=$'\033[0;32m'
  C_YELLOW=$'\033[1;33m'
  C_BLUE=$'\033[0;34m'
  C_BOLD=$'\033[1m'
  C_RESET=$'\033[0m'
else
  C_RED=""
  C_GREEN=""
  C_YELLOW=""
  C_BLUE=""
  C_BOLD=""
  C_RESET=""
fi

# === Args parsing ===
while [[ $# -gt 0 ]]; do
  case "$1" in
    --host)       HOST="$2"; shift 2 ;;
    --port)       PORT="$2"; shift 2 ;;
    --auth-token) AUTH_TOKEN_VAL="$2"; shift 2 ;;
    --env-file)   ENV_FILE="$2"; shift 2 ;;
    --timeout)    TIMEOUT="$2"; shift 2 ;;
    -h|--help)
      sed -n '2,20p' "$0" | sed 's/^# *//'
      exit 0
      ;;
    *)
      echo "Unknown arg: $1" >&2
      exit 2
      ;;
  esac
done

# === Load token from env file si pas fourni ===
if [[ -z "${AUTH_TOKEN_VAL:-}" && -f "$ENV_FILE" ]]; then
  AUTH_TOKEN_VAL="$(grep '^BRIDGE_AUTH_TOKEN=' "$ENV_FILE" | cut -d= -f2- | tr -d '"' | tr -d "'" || true)"
fi

BASE_URL="http://${HOST}:${PORT}"
PASS=0
FAIL=0

# === Helpers ===
have_jq() { command -v jq >/dev/null 2>&1; }

check() {
  local name="$1"
  local result="$2"
  if [[ "$result" == "ok" ]]; then
    echo -e "  ${C_GREEN}OK${C_RESET} $name"
    PASS=$((PASS + 1))
  else
    echo -e "  ${C_RED}FAIL${C_RESET} $name"
    FAIL=$((FAIL + 1))
  fi
}

section() {
  echo
  echo -e "${C_BOLD}${C_BLUE}>> $1${C_RESET}"
}

# === Banner ===
echo -e "${C_BOLD}=======================================================${C_RESET}"
echo -e "${C_BOLD}  Overmind Bridge - Smoke Test${C_RESET}"
echo -e "${C_BOLD}  Target: ${BASE_URL}${C_RESET}"
echo -e "${C_BOLD}=======================================================${C_RESET}"

# === Test 1 : service joignable ===
section "1. Reachability"
HTTP_CODE=$(curl -sS --max-time "$TIMEOUT" -o /dev/null -w "%{http_code}" \
    "$BASE_URL/health" 2>/dev/null || echo "000")
if echo "$HTTP_CODE" | grep -qE '^(200|401|403)$'; then
  check "HTTP /health repond [200/401/403]" ok
else
  check "HTTP /health ne repond pas - bridge down" fail
  echo
  echo -e "${C_RED}Bridge inaccessible. Abandon.${C_RESET}"
  echo -e "  Verifier : ${C_YELLOW}systemctl status overmind-bridge${C_RESET}"
  exit 1
fi

# === Test 2 : /health retourne un JSON valide ===
section "2. /health endpoint"
HEALTH_BODY=$(curl -sS --max-time "$TIMEOUT" "$BASE_URL/health" 2>/dev/null || true)

if have_jq; then
  HEALTH_STATUS=$(echo "$HEALTH_BODY" | jq -r '.status // "missing"' 2>/dev/null)
else
  HEALTH_STATUS=$(echo "$HEALTH_BODY" | grep -oE '"status"[[:space:]]*:[[:space:]]*"[^"]+"' | head -1 | cut -d'"' -f4)
fi

if [[ -n "${HEALTH_STATUS:-}" && "$HEALTH_STATUS" != "missing" ]]; then
  check "/health expose un status : $HEALTH_STATUS" ok
else
  check "/health n expose pas de status - endpoint casse" fail
fi

# === Build AUTH_HEADER array for reuse ===
AUTH_HEADER=()
if [[ -n "${AUTH_TOKEN_VAL:-}" ]]; then
  AUTH_HEADER=(-H "Authorization: Bearer ${AUTH_TOKEN_VAL}")
fi

# === Test 3 : auth requise si token configure ===
section "3. Authentication"
if [[ -n "${AUTH_TOKEN_VAL:-}" ]]; then
  HTTP_NO_AUTH=$(curl -sS --max-time "$TIMEOUT" -o /dev/null -w "%{http_code}" \
    -X POST "$BASE_URL/rpc" \
    -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":1,"method":"health.ping","params":{}}' 2>/dev/null || echo "000")

  if [[ "$HTTP_NO_AUTH" == "401" ]]; then
    check "Sans token -> 401, auth actif" ok
  else
    check "Sans token -> $HTTP_NO_AUTH [attendu: 401]" fail
  fi

  HTTP_WITH_AUTH=$(curl -sS --max-time "$TIMEOUT" -o /dev/null -w "%{http_code}" \
    -X POST "$BASE_URL/rpc" \
    "${AUTH_HEADER[@]}" \
    -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":1,"method":"health.ping","params":{}}' 2>/dev/null || echo "000")

  if [[ "$HTTP_WITH_AUTH" == "200" ]]; then
    check "Avec token -> 200, auth OK" ok
  else
    check "Avec token -> $HTTP_WITH_AUTH [attendu: 200]" fail
  fi
else
  HTTP_OPEN=$(curl -sS --max-time "$TIMEOUT" -o /dev/null -w "%{http_code}" \
    -X POST "$BASE_URL/rpc" \
    -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":1,"method":"health.ping","params":{}}' 2>/dev/null || echo "000")

  if [[ "$HTTP_OPEN" == "200" ]]; then
    check "/rpc ouvert, auth non configuree" ok
  else
    check "/rpc ouvert -> $HTTP_OPEN [attendu: 200]" fail
  fi
fi

# === Test 4 : health.ping RPC ===
section "4. JSON-RPC methods"
PING_BODY=$(curl -sS --max-time "$TIMEOUT" \
  "${AUTH_HEADER[@]}" \
  -H 'Content-Type: application/json' \
  -X POST "$BASE_URL/rpc" \
  -d '{"jsonrpc":"2.0","id":1,"method":"health.ping","params":{}}' 2>/dev/null || true)

if echo "$PING_BODY" | grep -q '"pong"[[:space:]]*:[[:space:]]*true'; then
  check "RPC health.ping repond" ok
else
  check "RPC health.ping echoue - body: ${PING_BODY:0:100}" fail
fi

# === Test 5 : JSON-RPC validation (params invalides) ===
section "5. Error handling"
INVALID_BODY=$(curl -sS --max-time "$TIMEOUT" \
  "${AUTH_HEADER[@]}" \
  -H 'Content-Type: application/json' \
  -X POST "$BASE_URL/rpc" \
  -d '{"jsonrpc":"2.0","id":1,"method":"agent.run","params":{}}' 2>/dev/null || true)

if echo "$INVALID_BODY" | grep -q '"code"[[:space:]]*:[[:space:]]*-32602'; then
  check "Params invalides -> -32602 Invalid params" ok
else
  check "Params invalides - code attendu: -32602, recu: $INVALID_BODY" fail
fi

# === Test 6 : batch request ===
section "6. Batch RPC"
BATCH_BODY=$(curl -sS --max-time "$TIMEOUT" \
  "${AUTH_HEADER[@]}" \
  -H 'Content-Type: application/json' \
  -X POST "$BASE_URL/rpc" \
  -d '[\
    {"jsonrpc":"2.0","id":1,"method":"health.ping","params":{}},\
    {"jsonrpc":"2.0","id":2,"method":"health.ping","params":{}}\
  ]' 2>/dev/null || true)

BATCH_COUNT=$(echo "$BATCH_BODY" | grep -oE '"id"[[:space:]]*:[[:space:]]*[12]' | wc -l | tr -d ' ')
if [[ "$BATCH_COUNT" == "2" ]]; then
  check "Batch RPC retourne 2 reponses" ok
else
  check "Batch RPC - recu: $BATCH_COUNT reponses [attendu: 2]" fail
fi

# === Resume ===
echo
echo -e "${C_BOLD}=======================================================${C_RESET}"
if [[ $FAIL -eq 0 ]]; then
  echo -e "${C_GREEN}${C_BOLD}  OK $PASS tests OK, 0 echec${C_RESET}"
  echo -e "${C_GREEN}  Bridge operationnel sur ${BASE_URL}${C_RESET}"
  echo -e "${C_BOLD}=======================================================${C_RESET}"
  exit 0
else
  echo -e "${C_RED}${C_BOLD}  FAIL $FAIL echec(s), $PASS tests OK${C_RESET}"
  echo
  echo -e "  ${C_YELLOW}Diagnostic :${C_RESET}"
  echo -e "    1. ${C_YELLOW}systemctl status overmind-bridge${C_RESET}"
  echo -e "    2. ${C_YELLOW}journalctl -u overmind-bridge -n 100${C_RESET}"
  echo -e "    3. ${C_YELLOW}curl -v $BASE_URL/health${C_RESET}"
  echo -e "${C_BOLD}=======================================================${C_RESET}"
  exit 1
fi
