#!/bin/bash
# Round 11 API Contract Test Script
# Tests all API endpoints for correctness, error handling, and boundary conditions

BASE="http://localhost:8080/api/v1"
PASS=0
FAIL=0
RESULTS=""

# Helper: run a test and record result
test_case() {
    local name="$1"
    local expected="$2"
    local method="$3"
    local url="$4"
    local data="$5"
    local auth="$6"

    if [ -n "$data" ]; then
        resp=$(curl -s -w "\n%{http_code}" -X "$method" "$url" \
            -H "Content-Type: application/json" \
            ${auth:+-H "Authorization: Bearer $auth"} \
            -d "$data" 2>&1)
    else
        resp=$(curl -s -w "\n%{http_code}" -X "$method" "$url" \
            -H "Content-Type: application/json" \
            ${auth:+-H "Authorization: Bearer $auth"} 2>&1)
    fi

    actual=$(echo "$resp" | tail -1)
    body=$(echo "$resp" | sed '$d')

    if [ "$actual" = "$expected" ]; then
        PASS=$((PASS + 1))
        RESULTS+="PASS | $name | $expected | $actual\n"
    else
        FAIL=$((FAIL + 1))
        RESULTS+="FAIL | $name | $expected | $actual | body=${body:0:120}\n"
    fi
}

echo "============================================"
echo " Round 11 API Contract Test Suite"
echo " Gateway: $BASE"
echo " Started at $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================"
echo ""

# ============================================================
# PART 1: Health + Public
# ============================================================
echo "--- Part 1: Health & Public Endpoints ---"

test_case "GET /health" "200" "GET" "$BASE/health"
test_case "HEAD /health" "200" "HEAD" "$BASE/health"

# ============================================================
# PART 2: Auth - Register
# ============================================================
echo "--- Part 2: Auth Register ---"

# Use unique username to avoid conflicts
UN="testapi_$(date +%s)"
PW="TestPass123!"

test_case "Register: missing username" "400" "POST" "$BASE/auth/register" \
    '{"password":"Test123!","email":"test@test.com","nickname":"Test","verify_code":"000000"}'

test_case "Register: missing password" "400" "POST" "$BASE/auth/register" \
    '{"username":"testuser","email":"test@test.com","nickname":"Test","verify_code":"000000"}'

test_case "Register: username too short (<3)" "400" "POST" "$BASE/auth/register" \
    '{"username":"ab","password":"Test123!","email":"test@test.com","nickname":"Test","verify_code":"000000"}'

test_case "Register: username too long (>32)" "400" "POST" "$BASE/auth/register" \
    '{"username":"abcdefghijklmnopqrstuvwxyz1234567890","password":"Test123!","email":"test@test.com","nickname":"Test","verify_code":"000000"}'

test_case "Register: username with special chars" "400" "POST" "$BASE/auth/register" \
    '{"username":"user@name!","password":"Test123!","email":"test@test.com","nickname":"Test","verify_code":"000000"}'

test_case "Register: password too short (<6)" "400" "POST" "$BASE/auth/register" \
    '{"username":"test_abc","password":"Ab1!","email":"test@test.com","nickname":"Test","verify_code":"000000"}'

test_case "Register: normal registration" "201" "POST" "$BASE/auth/register" \
    "{\"username\":\"$UN\",\"password\":\"$PW\",\"email\":\"test@test.com\",\"nickname\":\"TestUser\",\"verify_code\":\"000000\"}"

# Try to register same username again
test_case "Register: duplicate username" "409" "POST" "$BASE/auth/register" \
    "{\"username\":\"$UN\",\"password\":\"$PW\",\"email\":\"test@test.com\",\"nickname\":\"TestUser\",\"verify_code\":\"000000\"}"

# ============================================================
# PART 3: Auth - Login
# ============================================================
echo "--- Part 3: Auth Login ---"

test_case "Login: wrong username" "401" "POST" "$BASE/auth/login" \
    '{"username":"nonexistent_user_99","password":"TestPass123!"}'

test_case "Login: wrong password" "401" "POST" "$BASE/auth/login" \
    "{\"username\":\"$UN\",\"password\":\"WrongPass999!\"}"

# Correct login
LOGIN_RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE/auth/login" \
    -H "Content-Type: application/json" \
    -d "{\"username\":\"$UN\",\"password\":\"$PW\"}")
LOGIN_CODE=$(echo "$LOGIN_RESP" | tail -1)
LOGIN_BODY=$(echo "$LOGIN_RESP" | sed '$d')

if [ "$LOGIN_CODE" = "200" ]; then
    TOKEN=$(echo "$LOGIN_BODY" | python3 -c "import sys,json;print(json.load(sys.stdin).get('token',''))" 2>/dev/null)
    USER_ID=$(echo "$LOGIN_BODY" | python3 -c "import sys,json;print(json.load(sys.stdin).get('user_id',''))" 2>/dev/null)
    PASS=$((PASS + 1))
    RESULTS+="PASS | Login: correct credentials | 200 | 200\n"
    echo "  -> Got token OK, user_id=$USER_ID"
else
    FAIL=$((FAIL + 1))
    RESULTS+="FAIL | Login: correct credentials | 200 | $LOGIN_CODE | body=${LOGIN_BODY:0:120}\n"
    echo "  -> Login FAILED: $LOGIN_CODE - $LOGIN_BODY"
    TOKEN=""
fi

# Admin login
ADMIN_RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE/auth/login" \
    -H "Content-Type: application/json" \
    -d '{"username":"admin","password":"admin123"}')
ADMIN_CODE=$(echo "$ADMIN_RESP" | tail -1)
ADMIN_BODY=$(echo "$ADMIN_RESP" | sed '$d')
if [ "$ADMIN_CODE" = "200" ]; then
    ADMIN_TOKEN=$(echo "$ADMIN_BODY" | python3 -c "import sys,json;print(json.load(sys.stdin).get('token',''))" 2>/dev/null)
    PASS=$((PASS + 1))
    RESULTS+="PASS | Login: admin credentials | 200 | 200\n"
    echo "  -> Admin token OK"
else
    FAIL=$((FAIL + 1))
    RESULTS+="FAIL | Login: admin credentials | 200 | $ADMIN_CODE | body=${ADMIN_BODY:0:120}\n"
    echo "  -> Admin login FAILED: $ADMIN_CODE"
    ADMIN_TOKEN=""
fi

# Validate JWT token - try to use it
if [ -n "$TOKEN" ]; then
    REFRESH_RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE/auth/refresh" \
        -H "Authorization: Bearer $TOKEN")
    REFRESH_CODE=$(echo "$REFRESH_RESP" | tail -1)
    if [ "$REFRESH_CODE" = "200" ]; then
        PASS=$((PASS + 1))
        RESULTS+="PASS | JWT token valid (refresh) | 200 | 200\n"
    else
        FAIL=$((FAIL + 1))
        RESULTS+="FAIL | JWT token valid (refresh) | 200 | $REFRESH_CODE\n"
    fi
fi

# Login: missing fields
test_case "Login: missing password" "400" "POST" "$BASE/auth/login" \
    '{"username":"testuser"}'

test_case "Login: empty body" "400" "POST" "$BASE/auth/login" '{}'

test_case "Login: username format invalid" "400" "POST" "$BASE/auth/login" \
    '{"username":"ab","password":"Test123!"}'

# ============================================================
# PART 4: Session API
# ============================================================
echo "--- Part 4: Session API ---"

# Unauthenticated
test_case "Sessions: list no auth" "401" "GET" "$BASE/sessions"
test_case "Sessions: create no auth" "401" "POST" "$BASE/sessions" '{"title":"Test"}'

if [ -n "$TOKEN" ]; then
    # Authenticated - List
    test_case "Sessions: list with auth" "200" "GET" "$BASE/sessions" "" "$TOKEN"

    # Create session
    SESS_RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE/sessions" \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $TOKEN" \
        -d '{"title":"Round 11 Test Session"}')
    SESS_CODE=$(echo "$SESS_RESP" | tail -1)
    SESS_BODY=$(echo "$SESS_RESP" | sed '$d')
    SESS_ID=$(echo "$SESS_BODY" | python3 -c "import sys,json;print(json.load(sys.stdin).get('id',''))" 2>/dev/null)

    if [ "$SESS_CODE" = "201" ]; then
        PASS=$((PASS + 1))
        RESULTS+="PASS | Sessions: create | 201 | 201\n"
        echo "  -> Created session: $SESS_ID"
    else
        FAIL=$((FAIL + 1))
        RESULTS+="FAIL | Sessions: create | 201 | $SESS_CODE\n"
    fi

    # Get session
    if [ -n "$SESS_ID" ]; then
        test_case "Sessions: get existing" "200" "GET" "$BASE/sessions/$SESS_ID" "" "$TOKEN"
    fi

    # Get non-existent session
    test_case "Sessions: get non-existent" "404" "GET" "$BASE/sessions/session_nonexistent123" "" "$TOKEN"

    # Create with empty title (should default)
    test_case "Sessions: create empty title" "201" "POST" "$BASE/sessions" '{}' "$TOKEN"

    # Delete session
    if [ -n "$SESS_ID" ]; then
        test_case "Sessions: delete existing" "200" "DELETE" "$BASE/sessions/$SESS_ID" "" "$TOKEN"
    fi

    # Delete non-existent
    test_case "Sessions: delete non-existent" "200" "DELETE" "$BASE/sessions/session_nonexistent" "" "$TOKEN"

    # Get messages for non-existent session
    test_case "Sessions: messages non-existent" "200" "GET" "$BASE/sessions/session_nonexistent/messages" "" "$TOKEN"

    # Test cross-user access
    if [ -n "$ADMIN_TOKEN" ] && [ -n "$SESS_ID" ]; then
        echo "  -> Testing cross-user access..."
    fi
else
    FAIL=$((FAIL + 6))
    echo "  -> SKIPPED (no token)"
fi

# ============================================================
# PART 5: Files API
# ============================================================
echo "--- Part 5: Files API ---"
test_case "Files: list no auth" "401" "GET" "$BASE/files"

if [ -n "$TOKEN" ]; then
    test_case "Files: list with auth" "200" "GET" "$BASE/files" "" "$TOKEN"
    test_case "Files: get non-existent" "404" "GET" "$BASE/files/file_nonexistent" "" "$TOKEN"
else
    FAIL=$((FAIL + 2))
fi

# ============================================================
# PART 6: Knowledge API
# ============================================================
echo "--- Part 6: Knowledge API ---"
test_case "Knowledge: list bases no auth" "401" "GET" "$BASE/knowledge/bases"

if [ -n "$TOKEN" ]; then
    test_case "Knowledge: list bases with auth" "200" "GET" "$BASE/knowledge/bases" "" "$TOKEN"
    test_case "Knowledge: get non-existent" "404" "GET" "$BASE/knowledge/bases/kb_nonexistent" "" "$TOKEN"
else
    FAIL=$((FAIL + 2))
fi

# ============================================================
# PART 7: Automation API
# ============================================================
echo "--- Part 7: Automation API ---"
test_case "Automation: list rules no auth" "401" "GET" "$BASE/automation/rules"

if [ -n "$TOKEN" ]; then
    test_case "Automation: list rules with auth" "200" "GET" "$BASE/automation/rules" "" "$TOKEN"
    test_case "Automation: list scenes with auth" "200" "GET" "$BASE/automation/scenes" "" "$TOKEN"
    test_case "Automation: get non-existent rule" "404" "GET" "$BASE/automation/rules/rule_nonexistent" "" "$TOKEN"
else
    FAIL=$((FAIL + 3))
fi

# ============================================================
# PART 8: Reminders API
# ============================================================
echo "--- Part 8: Reminders API ---"
test_case "Reminders: list no auth" "401" "GET" "$BASE/reminders"

if [ -n "$TOKEN" ]; then
    test_case "Reminders: list with auth" "200" "GET" "$BASE/reminders" "" "$TOKEN"
    test_case "Reminders: create missing fields" "400" "POST" "$BASE/reminders" '{}' "$TOKEN"
else
    FAIL=$((FAIL + 2))
fi

# ============================================================
# PART 9: Briefings API
# ============================================================
echo "--- Part 9: Briefings API ---"
test_case "Briefings: get no auth" "401" "GET" "$BASE/briefings"

if [ -n "$TOKEN" ]; then
    test_case "Briefings: get with auth" "200" "GET" "$BASE/briefings" "" "$TOKEN"
    test_case "Briefings: latest with auth" "200" "GET" "$BASE/briefings/latest" "" "$TOKEN"
else
    FAIL=$((FAIL + 2))
fi

# ============================================================
# PART 10: Notifications API
# ============================================================
echo "--- Part 10: Notifications API ---"
test_case "Notifications: push no auth" "401" "POST" "$BASE/notifications/push" '{"message":"test"}'

if [ -n "$TOKEN" ]; then
    test_case "Notifications: push empty" "400" "POST" "$BASE/notifications/push" '{}' "$TOKEN"
else
    FAIL=$((FAIL + 1))
fi

# ============================================================
# PART 11: Memories API
# ============================================================
echo "--- Part 11: Memories API ---"
test_case "Memories: search no auth" "401" "GET" "$BASE/memory/search"

if [ -n "$TOKEN" ]; then
    test_case "Memories: search with auth" "200" "GET" "$BASE/memory/search?q=test" "" "$TOKEN"
    test_case "Memories: list with auth" "200" "GET" "$BASE/memory" "" "$TOKEN"
    test_case "Memories: add missing fields" "400" "POST" "$BASE/memory" '{}' "$TOKEN"
else
    FAIL=$((FAIL + 3))
fi

# ============================================================
# PART 12: Voice API
# ============================================================
echo "--- Part 12: Voice API ---"
if [ -n "$TOKEN" ]; then
    test_case "Voice: status with auth" "200" "GET" "$BASE/voice/status" "" "$TOKEN"
else
    FAIL=$((FAIL + 1))
fi

# ============================================================
# PART 13: Admin endpoints
# ============================================================
echo "--- Part 13: Admin endpoints ---"
if [ -n "$ADMIN_TOKEN" ]; then
    test_case "Admin: sessions with admin" "200" "GET" "$BASE/admin/sessions" "" "$ADMIN_TOKEN"
    test_case "Admin: sessions/active with admin" "200" "GET" "$BASE/admin/sessions/active" "" "$ADMIN_TOKEN"
else
    FAIL=$((FAIL + 2))
fi

# Non-admin user trying admin
if [ -n "$TOKEN" ]; then
    test_case "Admin: sessions without admin" "403" "GET" "$BASE/admin/sessions" "" "$TOKEN"
else
    FAIL=$((FAIL + 1))
fi

# ============================================================
# PART 14: Invalid token
# ============================================================
echo "--- Part 14: Invalid Token ---"
test_case "Sessions: invalid token" "401" "GET" "$BASE/sessions" "" "invalidtoken12345"
test_case "Sessions: expired/malformed" "401" "GET" "$BASE/sessions" "" "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8k"

# ============================================================
# PART 15: Token refresh
# ============================================================
echo "--- Part 15: Token Refresh ---"
test_case "Refresh: no auth" "401" "POST" "$BASE/auth/refresh"
test_case "Refresh: invalid token" "401" "POST" "$BASE/auth/refresh" "" "invalidtoken"

# ============================================================
# Summary
# ============================================================
echo ""
echo "============================================"
echo " TEST SUMMARY"
echo "============================================"
TOTAL=$((PASS + FAIL))
echo "Total: $TOTAL | Passed: $PASS | Failed: $FAIL"
echo ""

echo -e "$RESULTS" | column -t -s '|'

echo ""
echo "============================================"
echo " Test run completed at $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================"

# Save the token and user info for reference
if [ -n "$TOKEN" ]; then
    echo "TOKEN=$TOKEN" > /tmp/round11_testenv
    echo "USER_ID=$USER_ID" >> /tmp/round11_testenv
    echo "ADMIN_TOKEN=$ADMIN_TOKEN" >> /tmp/round11_testenv
    echo "TEST_USER=$UN" >> /tmp/round11_testenv
fi
