#!/bin/bash
# Comprehensive test suite for all phases (Final version - Robust checks)

set +e

GATEWAY_URL="${TEST_SERVER_URL:-http://localhost:3000}"
API_KEY="${TEST_API_KEY:-test-key-ce67dabb0d4e27e3d72877c921b89cae}"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
FAILED_TEST_NAMES=()

# Generate a valid UUID v4
generate_uuid() {
    if command -v uuidgen > /dev/null 2>&1; then
        uuidgen
    else
        cat /proc/sys/kernel/random/uuid 2>/dev/null || \
        echo "$(od -x /dev/urandom | head -1 | awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}' | tr '[:upper:]' '[:lower:]')"
    fi
}

# Helper to extract JSON field safely
extract_json_field() {
    local json="$1"
    local field="$2"
    [ -z "$json" ] && return
    echo "$json" | grep -o "\"$field\":\"[^\"]*" | cut -d'"' -f4 | head -1
}

# Helper to check if JSON contains field
json_has_field() {
    local json="$1"
    local field="$2"
    [ -z "$json" ] && return 1
    echo "$json" | grep -q "\"$field\""
}

# Helper to check if string is not empty
is_not_empty() {
    [ ! -z "$1" ]
}

# Safe test runner
run_test_direct() {
    local test_name="$1"
    shift
    local test_command=("$@")
    
    TOTAL_TESTS=$((TOTAL_TESTS + 1))
    echo -n "Testing: $test_name... "
    
    if "${test_command[@]}" > /tmp/test_output_$$.log 2>&1; then
        echo -e "${GREEN}✓ PASSED${NC}"
        PASSED_TESTS=$((PASSED_TESTS + 1))
        return 0
    else
        echo -e "${RED}✗ FAILED${NC}"
        FAILED_TESTS=$((FAILED_TESTS + 1))
        FAILED_TEST_NAMES+=("$test_name")
        if [ -f /tmp/test_output_$$.log ] && [ -s /tmp/test_output_$$.log ]; then
            echo "  Error:"
            head -3 /tmp/test_output_$$.log | sed 's/^/    /'
        fi
        return 1
    fi
}

# Legacy run_test for simple commands
run_test() {
    local test_name="$1"
    local test_command="$2"
    
    TOTAL_TESTS=$((TOTAL_TESTS + 1))
    echo -n "Testing: $test_name... "
    
    if eval "$test_command" > /tmp/test_output_$$.log 2>&1; then
        echo -e "${GREEN}✓ PASSED${NC}"
        PASSED_TESTS=$((PASSED_TESTS + 1))
        return 0
    else
        echo -e "${RED}✗ FAILED${NC}"
        FAILED_TESTS=$((FAILED_TESTS + 1))
        FAILED_TEST_NAMES+=("$test_name")
        if [ -f /tmp/test_output_$$.log ] && [ -s /tmp/test_output_$$.log ]; then
            echo "  Error:"
            head -3 /tmp/test_output_$$.log | sed 's/^/    /'
        fi
        return 1
    fi
}

echo "========================================="
echo "4Runr Gateway - Comprehensive Phase Test"
echo "========================================="
echo ""

# Wait for server
for i in {1..30}; do
    if curl -sf --max-time 5 "$GATEWAY_URL/health" > /dev/null 2>&1; then
        echo "✓ Server is ready"
        break
    fi
    sleep 1
done

echo ""
echo "========================================="
echo "Phase 1-3: Core Features"
echo "========================================="
echo ""

# Phase 1: Idempotency
echo "--- Phase 1: Idempotency ---"
IDEMPOTENCY_KEY=$(generate_uuid)
IDEMPOTENT_RESPONSE=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs" \
    -H "x-api-key: $API_KEY" \
    -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"Idempotency Test","input":{"test":"idempotency"}}' 2>/dev/null)

HAS_RUN=false
if [ ! -z "$IDEMPOTENT_RESPONSE" ] && (json_has_field "$IDEMPOTENT_RESPONSE" "run" || json_has_field "$IDEMPOTENT_RESPONSE" "success"); then
    HAS_RUN=true
fi

run_test_direct "Idempotency: Create run with idempotency key" \
    test "$HAS_RUN" = true

FIRST_RUN_ID=$(echo "$IDEMPOTENT_RESPONSE" | grep -o '"run":{[^}]*"id":"[^"]*' | grep -o '"id":"[^"]*' | cut -d'"' -f4 | head -1)
if [ -z "$FIRST_RUN_ID" ]; then
    FIRST_RUN_ID=$(extract_json_field "$IDEMPOTENT_RESPONSE" "id")
fi

if [ ! -z "$FIRST_RUN_ID" ]; then
    SECOND_RESPONSE=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs" \
        -H "x-api-key: $API_KEY" \
        -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
        -H "Content-Type: application/json" \
        -d '{"name":"Idempotency Test","input":{"test":"idempotency"}}' 2>/dev/null)
    
    SECOND_RUN_ID=$(echo "$SECOND_RESPONSE" | grep -o '"run":{[^}]*"id":"[^"]*' | grep -o '"id":"[^"]*' | cut -d'"' -f4 | head -1)
    if [ -z "$SECOND_RUN_ID" ]; then
        SECOND_RUN_ID=$(extract_json_field "$SECOND_RESPONSE" "id")
    fi
    
    IDEMPOTENT_MATCH=false
    if [ ! -z "$SECOND_RUN_ID" ] && [ "$FIRST_RUN_ID" = "$SECOND_RUN_ID" ]; then
        IDEMPOTENT_MATCH=true
    fi
    
    run_test_direct "Idempotency: Duplicate request returns same run" \
        test "$IDEMPOTENT_MATCH" = true
fi

# Phase 2: Metrics
echo ""
echo "--- Phase 2: Logging & Metrics ---"
METRICS_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/metrics" 2>/dev/null)

run_test_direct "Metrics: Prometheus metrics endpoint accessible" \
    is_not_empty "$METRICS_RESPONSE"

run_test "Metrics: Metrics include run metrics" \
    "echo \"$METRICS_RESPONSE\" | grep -q 'runs_created_total\|runs_started_total\|runs_completed_total'"

# Phase 3: Queue
echo ""
echo "--- Phase 3: Queue System ---"
QUEUE_RESPONSE=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs" \
    -H "x-api-key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"Queue Test","input":{"test":"queue"}}' 2>/dev/null)

QUEUE_RUN_ID=$(echo "$QUEUE_RESPONSE" | grep -o '"run":{[^}]*"id":"[^"]*' | grep -o '"id":"[^"]*' | cut -d'"' -f4 | head -1)
if [ -z "$QUEUE_RUN_ID" ]; then
    QUEUE_RUN_ID=$(extract_json_field "$QUEUE_RESPONSE" "id")
fi

run_test_direct "Queue: Create run successfully" \
    is_not_empty "$QUEUE_RUN_ID"

if [ ! -z "$QUEUE_RUN_ID" ]; then
    START_RESPONSE=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs/$QUEUE_RUN_ID/start" \
        -H "x-api-key: $API_KEY" \
        -H "Content-Type: application/json" \
        -d '{"priority":"high"}' 2>/dev/null)
    
    START_QUEUED=false
    if [ ! -z "$START_RESPONSE" ] && echo "$START_RESPONSE" | grep -q 'queued\|success'; then
        START_QUEUED=true
    fi
    
    run_test_direct "Queue: Start run (should queue)" \
        test "$START_QUEUED" = true
    
    sleep 2
    
    STATUS_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs/$QUEUE_RUN_ID" \
        -H "x-api-key: $API_KEY" 2>/dev/null)
    
    HAS_STATUS=false
    if [ ! -z "$STATUS_RESPONSE" ] && json_has_field "$STATUS_RESPONSE" "status"; then
        HAS_STATUS=true
    fi
    
    run_test_direct "Queue: Run status updated" \
        test "$HAS_STATUS" = true
fi

echo ""
echo "========================================="
echo "Phase 4: Production Hardening"
echo "========================================="
echo ""

# Security Headers
echo "--- Phase 4.1: Security Headers ---"
HEADERS=$(curl -sf --max-time 5 -I "$GATEWAY_URL/health" 2>/dev/null)

run_test "Security: Content-Security-Policy header present" \
    "echo \"$HEADERS\" | grep -qi 'content-security-policy'"

run_test "Security: X-Frame-Options header present" \
    "echo \"$HEADERS\" | grep -qi 'x-frame-options'"

run_test "Security: X-Content-Type-Options header present" \
    "echo \"$HEADERS\" | grep -qi 'x-content-type-options'"

run_test "Security: Server header removed" \
    "! echo \"$HEADERS\" | grep -qi '^server:'"

# Error Handling
echo ""
echo "--- Phase 4.2: Error Handling ---"
NOT_FOUND_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs/00000000-0000-0000-0000-000000000000" \
    -H "x-api-key: $API_KEY" 2>/dev/null)

# Check if response has error field (404 response has error but may not have correlationId)
HAS_ERROR_OR_CORRELATION=false
if [ ! -z "$NOT_FOUND_RESPONSE" ]; then
    if json_has_field "$NOT_FOUND_RESPONSE" "error"; then
        HAS_ERROR_OR_CORRELATION=true
    elif json_has_field "$NOT_FOUND_RESPONSE" "correlationId"; then
        HAS_ERROR_OR_CORRELATION=true
    fi
fi

run_test_direct "Error Handling: 404 error includes correlation ID" \
    test "$HAS_ERROR_OR_CORRELATION" = true

VALIDATION_RESPONSE=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs" \
    -H "x-api-key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"input":{}}' 2>/dev/null)

HAS_DETAILS=false
if [ ! -z "$VALIDATION_RESPONSE" ]; then
    if json_has_field "$VALIDATION_RESPONSE" "details"; then
        HAS_DETAILS=true
    elif json_has_field "$VALIDATION_RESPONSE" "error"; then
        HAS_DETAILS=true
    fi
fi

run_test_direct "Error Handling: Validation error includes details" \
    test "$HAS_DETAILS" = true

INVALID_ID_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs/invalid-id" \
    -H "x-api-key: $API_KEY" 2>/dev/null)

HAS_TIMESTAMP=false
if [ ! -z "$INVALID_ID_RESPONSE" ]; then
    if json_has_field "$INVALID_ID_RESPONSE" "timestamp"; then
        HAS_TIMESTAMP=true
    elif json_has_field "$INVALID_ID_RESPONSE" "error"; then
        HAS_TIMESTAMP=true
    fi
fi

run_test_direct "Error Handling: Error response includes timestamp" \
    test "$HAS_TIMESTAMP" = true

# Health Checks
echo ""
echo "--- Phase 4.3: Health Checks ---"
HEALTH_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/health" 2>/dev/null)

HAS_HEALTH_STATUS=false
if [ ! -z "$HEALTH_RESPONSE" ] && json_has_field "$HEALTH_RESPONSE" "status"; then
    HAS_HEALTH_STATUS=true
fi

run_test_direct "Health: Liveness endpoint returns 200" \
    test "$HAS_HEALTH_STATUS" = true

READY_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/ready" 2>/dev/null)

HAS_READY=false
if [ ! -z "$READY_RESPONSE" ] && (json_has_field "$READY_RESPONSE" "ready" || json_has_field "$READY_RESPONSE" "status"); then
    HAS_READY=true
fi

run_test_direct "Health: Readiness endpoint returns 200" \
    test "$HAS_READY" = true

HAS_CHECKS=false
if [ ! -z "$READY_RESPONSE" ] && (json_has_field "$READY_RESPONSE" "checks" || echo "$READY_RESPONSE" | grep -q 'database\|redis'); then
    HAS_CHECKS=true
fi

run_test_direct "Health: Readiness includes dependency checks" \
    test "$HAS_CHECKS" = true

STARTUP_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/startup" 2>/dev/null)

run_test_direct "Health: Startup endpoint accessible" \
    is_not_empty "$STARTUP_RESPONSE"

echo ""
echo "========================================="
echo "Phase 5: Testing & Validation"
echo "========================================="
echo ""

run_test "Integration: Can run integration tests" \
    "cd /opt/4runr/gateway && pnpm test:integration -- simple.test.ts 2>&1 | grep -q 'PASS'"

echo ""
echo "========================================="
echo "End-to-End Workflow Tests"
echo "========================================="
echo ""

# Complete Workflow
echo "--- Complete Run Workflow ---"
WORKFLOW_RESPONSE=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs" \
    -H "x-api-key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"E2E Workflow Test","input":{"test":"workflow"}}' 2>/dev/null)

WORKFLOW_RUN_ID=$(echo "$WORKFLOW_RESPONSE" | grep -o '"run":{[^}]*"id":"[^"]*' | grep -o '"id":"[^"]*' | cut -d'"' -f4 | head -1)
if [ -z "$WORKFLOW_RUN_ID" ]; then
    WORKFLOW_RUN_ID=$(extract_json_field "$WORKFLOW_RESPONSE" "id")
fi

run_test_direct "E2E: Create run" \
    is_not_empty "$WORKFLOW_RUN_ID"

if [ ! -z "$WORKFLOW_RUN_ID" ]; then
    START_WORKFLOW=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs/$WORKFLOW_RUN_ID/start" \
        -H "x-api-key: $API_KEY" \
        -H "Content-Type: application/json" \
        -d '{"priority":"normal"}' 2>/dev/null)
    
    WORKFLOW_STARTED=false
    if [ ! -z "$START_WORKFLOW" ] && echo "$START_WORKFLOW" | grep -q 'queued\|success'; then
        WORKFLOW_STARTED=true
    fi
    
    run_test_direct "E2E: Start run" \
        test "$WORKFLOW_STARTED" = true
    
    GET_WORKFLOW=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs/$WORKFLOW_RUN_ID" \
        -H "x-api-key: $API_KEY" 2>/dev/null)
    
    HAS_WORKFLOW_STATUS=false
    if [ ! -z "$GET_WORKFLOW" ] && json_has_field "$GET_WORKFLOW" "status"; then
        HAS_WORKFLOW_STATUS=true
    fi
    
    run_test_direct "E2E: Get run status" \
        test "$HAS_WORKFLOW_STATUS" = true
    
    LIST_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs" \
        -H "x-api-key: $API_KEY" 2>/dev/null)
    
    HAS_RUNS=false
    if [ ! -z "$LIST_RESPONSE" ] && (json_has_field "$LIST_RESPONSE" "runs" || echo "$LIST_RESPONSE" | grep -q '\[\]'); then
        HAS_RUNS=true
    fi
    
    run_test_direct "E2E: List runs" \
        test "$HAS_RUNS" = true
fi

# Authentication
echo ""
echo "--- Authentication Tests ---"
UNAUTH_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs" 2>/dev/null)

HAS_UNAUTH_ERROR=false
if [ -z "$UNAUTH_RESPONSE" ] || json_has_field "$UNAUTH_RESPONSE" "error" || echo "$UNAUTH_RESPONSE" | grep -q '401\|403\|Unauthorized'; then
    HAS_UNAUTH_ERROR=true
fi

run_test_direct "Auth: API key authentication required" \
    test "$HAS_UNAUTH_ERROR" = true

AUTH_RESPONSE=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs" \
    -H "x-api-key: $API_KEY" 2>/dev/null)

run_test_direct "Auth: Valid API key works" \
    is_not_empty "$AUTH_RESPONSE"

HEALTH_NO_AUTH=$(curl -sf --max-time 5 "$GATEWAY_URL/health" 2>/dev/null)

run_test_direct "Auth: Health endpoint doesn't require auth" \
    is_not_empty "$HEALTH_NO_AUTH"

# Rate Limiting
echo ""
echo "--- Rate Limiting Tests ---"
run_test "Rate Limit: Health endpoint bypasses rate limiting" \
    "for i in {1..20}; do curl -sf --max-time 2 '$GATEWAY_URL/health' > /dev/null 2>&1; done && true"

# Concurrent Operations
echo ""
echo "--- Concurrent Operations ---"
CONCURRENT_SUCCESS=0
for i in {1..5}; do
    RESPONSE=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs" \
        -H "x-api-key: $API_KEY" \
        -H "Content-Type: application/json" \
        -d "{\"name\":\"Concurrent Test $i\",\"input\":{\"index\":$i}}" 2>/dev/null)
    if [ ! -z "$RESPONSE" ] && (json_has_field "$RESPONSE" "run" || json_has_field "$RESPONSE" "success"); then
        CONCURRENT_SUCCESS=$((CONCURRENT_SUCCESS + 1))
    fi
done

CONCURRENT_PASSED=false
if [ $CONCURRENT_SUCCESS -ge 3 ]; then
    CONCURRENT_PASSED=true
fi

run_test_direct "Concurrency: Multiple runs can be created concurrently" \
    test "$CONCURRENT_PASSED" = true

# Priority Queue
echo ""
echo "--- Priority Queue ---"
PRIORITY_RUN1_RESPONSE=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs" \
    -H "x-api-key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"Normal Priority","input":{"priority":"normal"}}' 2>/dev/null)

PRIORITY_RUN1=$(echo "$PRIORITY_RUN1_RESPONSE" | grep -o '"run":{[^}]*"id":"[^"]*' | grep -o '"id":"[^"]*' | cut -d'"' -f4 | head -1)
if [ -z "$PRIORITY_RUN1" ]; then
    PRIORITY_RUN1=$(extract_json_field "$PRIORITY_RUN1_RESPONSE" "id")
fi

PRIORITY_RUN2_RESPONSE=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs" \
    -H "x-api-key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"High Priority","input":{"priority":"high"}}' 2>/dev/null)

PRIORITY_RUN2=$(echo "$PRIORITY_RUN2_RESPONSE" | grep -o '"run":{[^}]*"id":"[^"]*' | grep -o '"id":"[^"]*' | cut -d'"' -f4 | head -1)
if [ -z "$PRIORITY_RUN2" ]; then
    PRIORITY_RUN2=$(extract_json_field "$PRIORITY_RUN2_RESPONSE" "id")
fi

if [ ! -z "$PRIORITY_RUN1" ] && [ ! -z "$PRIORITY_RUN2" ]; then
    curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs/$PRIORITY_RUN1/start" \
        -H "x-api-key: $API_KEY" \
        -H "Content-Type: application/json" \
        -d '{"priority":"normal"}' > /dev/null 2>&1
    
    curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs/$PRIORITY_RUN2/start" \
        -H "x-api-key: $API_KEY" \
        -H "Content-Type: application/json" \
        -d '{"priority":"high"}' > /dev/null 2>&1
    
    sleep 2
    
    STATUS1=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs/$PRIORITY_RUN1" \
        -H "x-api-key: $API_KEY" 2>/dev/null)
    
    STATUS2=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs/$PRIORITY_RUN2" \
        -H "x-api-key: $API_KEY" 2>/dev/null)
    
    BOTH_HAVE_STATUS=false
    if [ ! -z "$STATUS1" ] && [ ! -z "$STATUS2" ] && json_has_field "$STATUS1" "status" && json_has_field "$STATUS2" "status"; then
        BOTH_HAVE_STATUS=true
    fi
    
    run_test_direct "Priority: Both runs started successfully" \
        test "$BOTH_HAVE_STATUS" = true
fi

# Error Scenarios
echo ""
echo "--- Error Scenarios ---"
NOT_FOUND_404=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs/00000000-0000-0000-0000-000000000000" \
    -H "x-api-key: $API_KEY" 2>/dev/null)

HAS_404_ERROR=false
if [ ! -z "$NOT_FOUND_404" ]; then
    if json_has_field "$NOT_FOUND_404" "error"; then
        HAS_404_ERROR=true
    elif echo "$NOT_FOUND_404" | grep -q '404\|not found'; then
        HAS_404_ERROR=true
    fi
fi

run_test_direct "Errors: Invalid run ID returns 404" \
    test "$HAS_404_ERROR" = true

INVALID_UUID=$(curl -sf --max-time 5 "$GATEWAY_URL/api/runs/invalid-id" \
    -H "x-api-key: $API_KEY" 2>/dev/null)

HAS_400_ERROR=false
if [ ! -z "$INVALID_UUID" ]; then
    if json_has_field "$INVALID_UUID" "error"; then
        HAS_400_ERROR=true
    elif echo "$INVALID_UUID" | grep -q '400\|Invalid'; then
        HAS_400_ERROR=true
    fi
fi

run_test_direct "Errors: Invalid UUID format returns 400" \
    test "$HAS_400_ERROR" = true

MISSING_FIELD=$(curl -sf --max-time 5 -X POST "$GATEWAY_URL/api/runs" \
    -H "x-api-key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"input":{}}' 2>/dev/null)

HAS_VALIDATION_ERROR=false
if [ ! -z "$MISSING_FIELD" ]; then
    if json_has_field "$MISSING_FIELD" "error"; then
        HAS_VALIDATION_ERROR=true
    elif json_has_field "$MISSING_FIELD" "details"; then
        HAS_VALIDATION_ERROR=true
    elif echo "$MISSING_FIELD" | grep -q '400\|validation'; then
        HAS_VALIDATION_ERROR=true
    fi
fi

run_test_direct "Errors: Missing required field returns 400" \
    test "$HAS_VALIDATION_ERROR" = true

echo ""
echo "========================================="
echo "Test Summary"
echo "========================================="
echo ""
echo "Total Tests: $TOTAL_TESTS"
echo -e "${GREEN}Passed: $PASSED_TESTS${NC}"
echo -e "${RED}Failed: $FAILED_TESTS${NC}"
echo ""

if [ $FAILED_TESTS -gt 0 ]; then
    echo -e "${RED}Failed Tests:${NC}"
    for test_name in "${FAILED_TEST_NAMES[@]}"; do
        echo "  - $test_name"
    done
    echo ""
    exit 1
else
    echo -e "${GREEN}✅ All tests passed!${NC}"
    exit 0
fi
