#!/usr/bin/env bash
# =====================================================================
# BSU Events API — Smoke Test
# Exercises the full API flow end-to-end.
# Usage: ./smoke_test.sh [BASE_URL]
#   defaults to http://localhost/event_api if no argument given
# =====================================================================

set -euo pipefail

BASE="${1:-http://localhost/event_api}"
PASS=0
FAIL=0

# Unique suffix so re-runs don't collide with UNIQUE constraints
TS=$(date +%s)
STUDENT_EMAIL="smoke_student_${TS}@bsu.ac.ug"
ADMIN_EMAIL="smoke_admin_${TS}@bsu.ac.ug"
ORGANIZER_EMAIL="smoke_organizer_${TS}@bsu.ac.ug"
NOSHOW_EMAIL="smoke_noshow_${TS}@bsu.ac.ug"

# ── Helpers ──────────────────────────────────────────────────────────

pass() { printf "  PASS  %s\n" "$1"; PASS=$((PASS + 1)); }
fail() { printf "  FAIL  %s — %s\n" "$1" "$2"; FAIL=$((FAIL + 1)); }

# Make a request and store result in $RESP and $CODE
request() {
    local method="$1" endpoint="$2" data="${3:-}" auth="${4:-}"
    local args=(-s -w '\n%{http_code}' --max-time 15)

    if [[ "$method" == "POST" && -n "$data" ]]; then
        args+=(-d "$data")
    fi
    if [[ -n "$auth" ]]; then
        args+=(-H "Authorization: Bearer $auth")
    fi

    RESP=$(curl "${args[@]}" -H "Content-Type: application/json" "${BASE}/${endpoint}")
    CODE=$(echo "$RESP" | tail -1)
    RESP=$(echo "$RESP" | sed '$d')
}

# Extract JSON field with grep fallback (no jq dependency)
field() { echo "$RESP" | grep -o "\"$1\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | head -1 | sed 's/.*: *"//;s/"$//'; }
field_bool() { echo "$RESP" | grep -o "\"$1\"[[:space:]]*:[[:space:]]*\(true\|false\)" | head -1 | sed 's/.*: *//'; }
http_ok() { [[ "$CODE" -ge 200 && "$CODE" -lt 300 ]]; }

assert_pass() {
    if http_ok && [[ "$(field_bool success)" == "true" ]]; then
        pass "$1"
    else
        fail "$1" "expected success:true, got HTTP $CODE"
    fi
}

assert_fail() {
    if ! http_ok || [[ "$(field_bool success)" == "false" ]]; then
        pass "$1"
    else
        fail "$1" "expected failure but got HTTP $CODE with success:true"
    fi
}

# ── Cleanup from previous runs ──────────────────────────────────────

cleanup() {
    echo ""
    echo "Cleaning up test data..."
    local ADMIN_TOKEN
    # Register a fresh admin to get a token, then delete test rows
    request POST register.php '{"fullname":"Cleanup Admin","email":"cleanup_test@bsu.ac.ug","password":"cleanpass123"}'
    ADMIN_TOKEN=$(field token)
    if [[ -z "$ADMIN_TOKEN" ]]; then
        echo "  Could not get cleanup token, skipping."
        return
    fi
    # Delete test users (email pattern: *_test@bsu.ac.ug)
    request POST manage_users.php '{"action":"deactivate","user_id":99999}' "$ADMIN_TOKEN" 2>/dev/null || true
}

# ── Run ─────────────────────────────────────────────────────────────

echo "========================================"
echo " BSU Events API — Smoke Test"
echo " Base: $BASE"
echo "========================================"
echo ""

STUDENT_TOKEN=""
ORGANIZER_TOKEN=""
ADMIN_TOKEN=""

# ── 1. Register a student ──────────────────────────────────────────

echo "1. Register a student"
request POST register.php \
    "{\"fullname\":\"Test Student\",\"email\":\"${STUDENT_EMAIL}\",\"password\":\"student123\"}"
if http_ok && [[ "$(field_bool success)" == "true" ]]; then
    pass "Register student"
else
    MSG=$(field message)
    if echo "$MSG" | grep -qi "already registered"; then
        pass "Register student (already exists — will login instead)"
    else
        fail "Register student" "$MSG"
    fi
fi

# ── 2. Login as the student ────────────────────────────────────────

echo "2. Login as student"
request POST login.php \
    "{\"email\":\"${STUDENT_EMAIL}\",\"password\":\"student123\"}"
if http_ok && [[ "$(field_bool success)" == "true" ]]; then
    STUDENT_TOKEN=$(field token)
    pass "Login student (token obtained)"
else
    fail "Login student" "could not obtain token"
    echo "FATAL: Cannot continue without student token."
    exit 1
fi

# ── 3. Browse events (no auth) ────────────────────────────────────

echo "3. Browse events"
request GET get_events.php
assert_pass "Browse events (no auth)"

# ── 4. View event details (no auth) ───────────────────────────────

echo "4. View event details"
request GET get_event_details.php?id=1
assert_pass "View event details (no auth)"

echo "5. View event details — missing id"
request GET get_event_details.php
assert_fail "View event details — no id (expect 400/404)"

# ── 6. RSVP the student to a seeded event ──────────────────────────

echo "6. RSVP student to event 1"
request POST rsvp.php \
    '{"event_id":1,"status":"Going"}' "$STUDENT_TOKEN"
# This may be a duplicate if the test was run before — check for expected error
if http_ok && [[ "$(field_bool success)" == "true" ]]; then
    pass "RSVP student to event 1"
else
    MSG=$(field message)
    if echo "$MSG" | grep -qi "already exists"; then
        pass "RSVP student to event 1 (already existed — acceptable)"
    else
        fail "RSVP student to event 1" "$MSG"
    fi
fi

# ── 7. Seed an admin via MySQL (register.php only creates students) ──

echo "7. Seed admin via MySQL"
ADMIN_HASH=$(php -r "echo password_hash('admin1234', PASSWORD_BCRYPT);")
/opt/lampp/bin/mysql -u root -p'owokunda' bsu_events -e \
    "INSERT IGNORE INTO users (fullname, email, password, role) VALUES ('Smoke Admin', '${ADMIN_EMAIL}', '${ADMIN_HASH}', 'admin')" 2>/dev/null
if [[ $? -eq 0 ]]; then
    pass "Seed admin"
else
    fail "Seed admin" "mysql insert failed"
fi

echo "8. Login as admin"
request POST login.php \
    "{\"email\":\"${ADMIN_EMAIL}\",\"password\":\"admin1234\"}"
if http_ok && [[ "$(field_bool success)" == "true" ]]; then
    ADMIN_TOKEN=$(field token)
    pass "Login admin (token obtained)"
else
    fail "Login admin" "could not obtain token"
fi

echo "9. Create organizer via manage_users"
request POST manage_users.php \
    "{\"action\":\"create_organizer\",\"fullname\":\"Smoke Organizer\",\"email\":\"${ORGANIZER_EMAIL}\",\"password\":\"org12345\"}" "$ADMIN_TOKEN"
if http_ok && [[ "$(field_bool success)" == "true" ]]; then
    pass "Create organizer account"
else
    MSG=$(field message)
    if echo "$MSG" | grep -qi "already registered"; then
        pass "Create organizer account (already exists — will login instead)"
    else
        fail "Create organizer account" "$MSG"
    fi
fi

echo "10. Login as organizer"
request POST login.php \
    "{\"email\":\"${ORGANIZER_EMAIL}\",\"password\":\"org12345\"}"
if http_ok && [[ "$(field_bool success)" == "true" ]]; then
    ORGANIZER_TOKEN=$(field token)
    pass "Login organizer (token obtained)"
else
    fail "Login organizer" "could not obtain token"
    echo "FATAL: Cannot continue without organizer token."
    exit 1
fi

# ── 11. Create a new event as organizer ────────────────────────────

echo "11. Create event"
request POST create_event.php \
    '{"title":"Smoke Test Event","description":"Auto-generated by smoke test","venue":"Test Hall","event_date":"2026-12-01","event_time":"10:00:00","capacity":50}' "$ORGANIZER_TOKEN"
assert_pass "Create event"

# Extract the new event id (last row for this organizer)
request GET get_events.php
NEW_EVENT_ID=$(echo "$RESP" | grep -o '"id"[[:space:]]*:[[:space:]]*[0-9]*' | tail -1 | grep -o '[0-9]*')
if [[ -z "$NEW_EVENT_ID" ]]; then
    NEW_EVENT_ID=6
    echo "  (fallback: using event id $NEW_EVENT_ID)"
fi

# ── 12. RSVP student to the new event ──────────────────────────────

echo "12. RSVP student to new event $NEW_EVENT_ID"
request POST rsvp.php \
    "{\"event_id\":$NEW_EVENT_ID,\"status\":\"Going\"}" "$STUDENT_TOKEN"
assert_pass "RSVP student to new event"

# ── 13. Check the student in ──────────────────────────────────────

echo "13. Check student in"
# Decode JWT payload to get student user_id
STUDENT_ID=$(echo "$STUDENT_TOKEN" | cut -d. -f2 | tr '_-' '/+' | base64 -d 2>/dev/null | grep -o '"user_id":[0-9]*' | grep -o '[0-9]*') || true
request POST checkin.php \
    "{\"user_id\":$STUDENT_ID,\"event_id\":$NEW_EVENT_ID}" "$ORGANIZER_TOKEN"
assert_pass "Check student in"

# ── 14. Submit feedback ───────────────────────────────────────────

echo "14. Submit feedback"
request POST submit_feedback.php \
    "{\"event_id\":$NEW_EVENT_ID,\"rating\":5,\"comment\":\"Smoke test feedback\"}" "$STUDENT_TOKEN"
assert_pass "Submit feedback"

echo "15. Submit feedback again (expect duplicate error)"
request POST submit_feedback.php \
    "{\"event_id\":$NEW_EVENT_ID,\"rating\":4,\"comment\":\"Duplicate feedback\"}" "$STUDENT_TOKEN"
assert_fail "Duplicate feedback (expect 403/409)"

# ── 16. Feedback from a student with no attendance ─────────────────

echo "16. Register second student (no attendance)"
request POST register.php \
    "{\"fullname\":\"No-Show Student\",\"email\":\"${NOSHOW_EMAIL}\",\"password\":\"nosh1234\"}"
if http_ok && [[ "$(field_bool success)" == "true" ]]; then
    pass "Register second student"
else
    MSG=$(field message)
    if echo "$MSG" | grep -qi "already registered"; then
        pass "Register second student (already exists — will login instead)"
    else
        fail "Register second student" "$MSG"
    fi
fi

request POST login.php \
    "{\"email\":\"${NOSHOW_EMAIL}\",\"password\":\"nosh1234\"}"
NOSHOW_TOKEN=$(field token)

echo "17. Feedback from student with no attendance (expect fail)"
request POST submit_feedback.php \
    "{\"event_id\":$NEW_EVENT_ID,\"rating\":3,\"comment\":\"Should fail\"}" "$NOSHOW_TOKEN"
assert_fail "Feedback without attendance (expect 403)"

# ── 18. RSVP without auth (expect 401) ───────────────────────────

echo "18. RSVP without auth (expect 401)"
request POST rsvp.php '{"event_id":1,"status":"Going"}'
assert_fail "RSVP without auth (expect 401)"

# ── 19. Generate report as admin ──────────────────────────────────

echo "19. Generate report as admin"
request GET generate_report.php "" "$ADMIN_TOKEN"
assert_pass "Generate report"

echo "20. Generate report without admin role (expect 403)"
request GET generate_report.php "" "$STUDENT_TOKEN"
assert_fail "Generate report as student (expect 403)"

# ── Summary ────────────────────────────────────────────────────────

echo ""
echo "========================================"
printf " Results: %d passed, %d failed\n" "$PASS" "$FAIL"
echo "========================================"

if [[ "$FAIL" -gt 0 ]]; then
    exit 1
fi
