#!/bin/bash
# ═══════════════════════════════════════════════════════════════════════════
#  WalkGuide — k6 Test Runner
#  Jalankan semua k6 scenarios secara berurutan atau individual.
#
#  Usage:
#    chmod +x run-all-tests.sh
#    ./run-all-tests.sh [mode] [BASE_URL]
#
#  Modes:
#    smoke    — 10 VUs, 1 menit (quick sanity check)
#    load     — 50 VUs, 5 menit (normal production load, WAJIB untuk exam)
#    stress   — 100 VUs, 10 menit (breaking point)
#    spike    — 0→200 VUs sudden spike
#    all      — jalankan smoke → load → stress → spike berurutan
#    auth     — hanya auth-flow.js
#    pairing  — hanya pairing-flow.js
#    location — hanya location-update.js
#    obstacle — hanya obstacle-logging.js
#    sos      — hanya sos-flow.js
#    notif    — hanya notification-send.js
#    timeline — hanya timeline-query.js
#
#  Contoh:
#    ./run-all-tests.sh load http://202.46.28.160:8080
#    ./run-all-tests.sh smoke
#    ./run-all-tests.sh all http://202.46.28.160:8080
# ═══════════════════════════════════════════════════════════════════════════

set -e

# ── Config ────────────────────────────────────────────────────────────────────
MODE="${1:-load}"
BASE_URL="${2:-http://202.46.28.160:8080}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
RESULTS_DIR="${SCRIPT_DIR}/k6-results"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")

# ── Colors ────────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color

# ── Helpers ───────────────────────────────────────────────────────────────────
log()  { echo -e "${CYAN}[$(date +%H:%M:%S)]${NC} $1"; }
ok()   { echo -e "${GREEN}[✅ OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[⚠️  WARN]${NC} $1"; }
err()  { echo -e "${RED}[❌ ERR]${NC} $1"; }
hr()   { echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"; }

# ── Pre-flight checks ─────────────────────────────────────────────────────────
hr
echo -e "${BOLD}  🦺 WalkGuide — k6 Load Test Runner${NC}"
echo -e "  Mode: ${YELLOW}${MODE}${NC} | Backend: ${YELLOW}${BASE_URL}${NC}"
hr

# Check k6 installed
if ! command -v k6 &> /dev/null; then
  err "k6 not installed!"
  echo "Install: https://k6.io/docs/getting-started/installation/"
  echo "Ubuntu: sudo apt-get install k6"
  echo "Mac:    brew install k6"
  echo "Docker: docker run grafana/k6 run ..."
  exit 1
fi

K6_VERSION=$(k6 version 2>&1 | head -1)
ok "k6 found: $K6_VERSION"

# Check Node.js (for result parsing)
if command -v node &> /dev/null; then
  ok "Node.js: $(node --version)"
else
  warn "Node.js not found — skipping HTML report generation"
fi

# Create results dir
mkdir -p "$RESULTS_DIR"
ok "Results dir: $RESULTS_DIR"

# ── Backend reachability check ────────────────────────────────────────────────
log "Checking backend reachability..."
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${BASE_URL}/api/v1/auth/ping" --max-time 10 2>/dev/null || echo "000")

if [ "$HTTP_STATUS" = "200" ]; then
  ok "Backend reachable (HTTP $HTTP_STATUS)"
elif [ "$HTTP_STATUS" = "000" ]; then
  warn "Backend not reachable or timeout. Continuing anyway (tests will fail gracefully)."
else
  warn "Backend returned HTTP $HTTP_STATUS. Continuing..."
fi

# ── k6 run helper ─────────────────────────────────────────────────────────────
run_k6() {
  local scenario_file="$1"
  local scenario_name="$2"
  local extra_args="${3:-}"

  local output_json="${RESULTS_DIR}/${scenario_name}_${TIMESTAMP}.ndjson"
  local summary_json="${RESULTS_DIR}/${scenario_name}_summary_${TIMESTAMP}.json"

  log "Running scenario: ${BOLD}${scenario_name}${NC}"
  log "Script: ${scenario_file}"

  local k6_cmd="k6 run \
    --out json=${output_json} \
    -e BASE_URL=${BASE_URL} \
    --summary-export=${summary_json} \
    --no-color \
    ${extra_args} \
    ${SCRIPT_DIR}/scenarios/${scenario_file}"

  echo "Command: $k6_cmd"
  hr

  if eval "$k6_cmd"; then
    ok "Scenario ${scenario_name} completed successfully"
  else
    warn "Scenario ${scenario_name} completed with threshold violations (check results)"
  fi

  # Parse results if Node.js available
  if command -v node &> /dev/null && [ -f "$output_json" ]; then
    log "Parsing results..."
    local parsed_json="${RESULTS_DIR}/${scenario_name}_parsed_${TIMESTAMP}.json"
    local html_report="${RESULTS_DIR}/${scenario_name}_report_${TIMESTAMP}.html"

    node "${SCRIPT_DIR}/utils/result-parser.js" "$output_json" "$parsed_json" 2>/dev/null || true
    node "${SCRIPT_DIR}/utils/html-reporter.js" "$parsed_json" "$html_report" 2>/dev/null || true

    if [ -f "$html_report" ]; then
      ok "HTML report: $html_report"
    fi
  fi

  echo ""
}

# ── Stage-specific k6 args ────────────────────────────────────────────────────
SMOKE_ARGS="--stage 30s:3 --stage 60s:10 --stage 30s:0"
# Note: --stage shorthand diganti inline di script JSON

# ── Test execution ─────────────────────────────────────────────────────────────
case "$MODE" in

  smoke)
    log "=== SMOKE TEST (10 VUs, 1 min) ==="
    run_k6 "auth-flow.js"      "smoke_auth"     "--vus 3 --duration 60s"
    run_k6 "location-update.js" "smoke_location" "--vus 3 --duration 60s"
    run_k6 "sos-flow.js"       "smoke_sos"      "--vus 2 --duration 60s"
    ;;

  load)
    log "=== LOAD TEST (50+ VUs, 5 min) — EXAM REQUIRED ==="
    run_k6 "auth-flow.js"        "load_auth"
    run_k6 "pairing-flow.js"     "load_pairing"
    run_k6 "location-update.js"  "load_location"
    run_k6 "obstacle-logging.js" "load_obstacle"
    run_k6 "sos-flow.js"         "load_sos"
    run_k6 "notification-send.js" "load_notif"
    run_k6 "timeline-query.js"   "load_timeline"
    ;;

  stress)
    log "=== STRESS TEST (100 VUs, 10 min) ==="
    run_k6 "location-update.js"  "stress_location"
    run_k6 "obstacle-logging.js" "stress_obstacle"
    run_k6 "notification-send.js" "stress_notif"
    run_k6 "timeline-query.js"   "stress_timeline"
    ;;

  spike)
    log "=== SPIKE TEST (0→200 VUs sudden) ==="
    run_k6 "location-update.js"  "spike_location"
    run_k6 "obstacle-logging.js" "spike_obstacle"
    ;;

  all)
    log "=== FULL TEST SUITE (smoke → load → stress → spike) ==="
    warn "Estimated total time: 30-45 minutes"
    read -p "Continue? [y/N] " confirm
    if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
      echo "Aborted."; exit 0
    fi

    # Smoke
    log "--- Phase 1: Smoke Test ---"
    run_k6 "auth-flow.js"      "fullsuite_smoke_auth"     "--vus 3 --duration 60s"
    run_k6 "location-update.js" "fullsuite_smoke_location" "--vus 3 --duration 60s"

    # Load
    log "--- Phase 2: Load Test ---"
    run_k6 "auth-flow.js"        "fullsuite_load_auth"
    run_k6 "location-update.js"  "fullsuite_load_location"
    run_k6 "obstacle-logging.js" "fullsuite_load_obstacle"
    run_k6 "sos-flow.js"         "fullsuite_load_sos"
    run_k6 "notification-send.js" "fullsuite_load_notif"
    run_k6 "timeline-query.js"   "fullsuite_load_timeline"

    # Stress
    log "--- Phase 3: Stress Test ---"
    run_k6 "location-update.js"  "fullsuite_stress_location"

    # Spike
    log "--- Phase 4: Spike Test ---"
    run_k6 "location-update.js"  "fullsuite_spike_location"
    ;;

  # Individual scenarios
  auth)     run_k6 "auth-flow.js"        "individual_auth" ;;
  pairing)  run_k6 "pairing-flow.js"     "individual_pairing" ;;
  location) run_k6 "location-update.js"  "individual_location" ;;
  obstacle) run_k6 "obstacle-logging.js" "individual_obstacle" ;;
  sos)      run_k6 "sos-flow.js"         "individual_sos" ;;
  notif)    run_k6 "notification-send.js" "individual_notif" ;;
  timeline) run_k6 "timeline-query.js"   "individual_timeline" ;;

  *)
    err "Unknown mode: $MODE"
    echo "Valid modes: smoke | load | stress | spike | all | auth | pairing | location | obstacle | sos | notif | timeline"
    exit 1
    ;;
esac

# ── Final summary ─────────────────────────────────────────────────────────────
hr
ok "All k6 tests finished!"
log "Results saved to: $RESULTS_DIR"
echo ""
echo "Files generated:"
ls -lh "$RESULTS_DIR"/*.{json,html} 2>/dev/null || echo "  (no files found)"
hr