#!/bin/bash
# Test endpoint response formats to identify inconsistencies
# Usage: ./scripts/test-endpoint-formats.sh [base_url]
# Example: ./scripts/test-endpoint-formats.sh http://localhost:8080/api/v1

set -e

# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Configuration
BASE_URL="${1:-http://localhost:8080/api/v1}"
OUTPUT_FILE="${2:-endpoint-formats-report.json}"
SWAGGER_SPEC="${3:-veza-backend-api/docs/swagger.json}"

echo -e "${BLUE}🔍 Testing endpoint response formats...${NC}"
echo -e "${BLUE}Base URL: ${BASE_URL}${NC}"
echo -e "${BLUE}Output: ${OUTPUT_FILE}${NC}"
echo ""

# Check if jq is available
if ! command -v jq &> /dev/null; then
    echo -e "${RED}❌ Error: jq is required but not installed${NC}"
    exit 1
fi

# Check if swagger spec exists
if [ ! -f "$SWAGGER_SPEC" ]; then
    echo -e "${YELLOW}⚠️  Warning: Swagger spec not found at $SWAGGER_SPEC${NC}"
    echo -e "${YELLOW}   Will test endpoints manually${NC}"
    SWAGGER_SPEC=""
fi

# Initialize results array
RESULTS="[]"

# Function to test an endpoint
test_endpoint() {
    local method=$1
    local path=$2
    local full_url="${BASE_URL}${path}"
    local description=$3
    
    echo -e "${BLUE}Testing: ${method} ${path}${NC}"
    
    # Build curl command based on method
    local curl_cmd="curl -s -w '\n%{http_code}' -X ${method}"
    
    # Add headers
    curl_cmd="${curl_cmd} -H 'Content-Type: application/json'"
    curl_cmd="${curl_cmd} -H 'X-API-Version: v1'"
    
    # Add body for POST/PUT/PATCH
    if [[ "$method" == "POST" || "$method" == "PUT" || "$method" == "PATCH" ]]; then
        # Try to determine if auth is needed (skip auth endpoints)
        if [[ "$path" == *"/auth/login"* ]] || [[ "$path" == *"/auth/register"* ]]; then
            curl_cmd="${curl_cmd} -d '{}'"
        else
            # For other endpoints, skip if they require auth (will get 401)
            curl_cmd="${curl_cmd} -d '{}'"
        fi
    fi
    
    # Execute request
    local response=$(eval "$curl_cmd '${full_url}'" 2>/dev/null || echo "")
    
    if [ -z "$response" ]; then
        echo -e "${YELLOW}  ⚠️  No response (endpoint may be down or require auth)${NC}"
        RESULTS=$(echo "$RESULTS" | jq --arg method "$method" \
            --arg path "$path" \
            --arg desc "$description" \
            --arg status "no_response" \
            --arg format "unknown" \
            '. += [{
                method: $method,
                path: $path,
                description: $desc,
                status: $status,
                format: $format,
                error: "No response received"
            }]')
        return
    fi
    
    # Extract HTTP status code (last line)
    local http_code=$(echo "$response" | tail -n1)
    local body=$(echo "$response" | sed '$d')
    
    # Determine response format
    local format="unknown"
    local has_success=$(echo "$body" | jq -r '.success // empty' 2>/dev/null || echo "")
    local has_data=$(echo "$body" | jq -r '.data // empty' 2>/dev/null || echo "")
    local has_error=$(echo "$body" | jq -r '.error // empty' 2>/dev/null || echo "")
    
    if [ "$http_code" == "200" ] || [ "$http_code" == "201" ]; then
        if [ -n "$has_success" ] && [ -n "$has_data" ]; then
            format="wrapped"
            echo -e "${GREEN}  ✅ Wrapped format: { success, data }${NC}"
        elif [ -n "$has_data" ] && [ -z "$has_success" ]; then
            format="direct_data"
            echo -e "${YELLOW}  ⚠️  Direct format: { data } (no success field)${NC}"
        else
            format="direct"
            echo -e "${YELLOW}  ⚠️  Direct format: no wrapper${NC}"
        fi
    elif [ "$http_code" == "401" ] || [ "$http_code" == "403" ]; then
        format="auth_required"
        echo -e "${YELLOW}  🔒 Auth required (${http_code})${NC}"
    elif [ "$http_code" == "404" ]; then
        format="not_found"
        echo -e "${YELLOW}  ❌ Not found (${http_code})${NC}"
    else
        format="error"
        echo -e "${YELLOW}  ⚠️  Error (${http_code})${NC}"
    fi
    
    # Add to results (handle non-JSON responses)
    local body_json="null"
    if [ -n "$body" ]; then
        # Try to parse as JSON first
        if echo "$body" | jq . >/dev/null 2>&1; then
            body_json=$(echo "$body" | jq -c .)
        else
            # Not valid JSON, store as escaped string (truncate to 200 chars)
            body_json=$(echo "$body" | head -c 200 | jq -Rs .)
        fi
    fi
    
    # Use conditional jq based on whether body_json is null
    if [ "$body_json" = "null" ]; then
        RESULTS=$(echo "$RESULTS" | jq --arg method "$method" \
            --arg path "$path" \
            --arg desc "$description" \
            --arg status "$http_code" \
            --arg format "$format" \
            '. += [{
                method: $method,
                path: $path,
                description: $desc,
                status: $status,
                format: $format,
                response_sample: null
            }]')
    else
        RESULTS=$(echo "$RESULTS" | jq --arg method "$method" \
            --arg path "$path" \
            --arg desc "$description" \
            --arg status "$http_code" \
            --arg format "$format" \
            --argjson body "$body_json" \
            '. += [{
                method: $method,
                path: $path,
                description: $desc,
                status: $status,
                format: $format,
                response_sample: $body
            }]')
    fi
}

# Extract endpoints from Swagger spec if available
if [ -n "$SWAGGER_SPEC" ] && [ -f "$SWAGGER_SPEC" ]; then
    echo -e "${GREEN}📋 Reading endpoints from Swagger spec...${NC}"
    
    # Get all paths and store in temp file to avoid subshell issues
    TMP_ENDPOINTS=$(mktemp)
    jq -r '.paths | to_entries[] | .key as $path | .value | to_entries[] | "\(.key | ascii_upcase) \($path)"' "$SWAGGER_SPEC" > "$TMP_ENDPOINTS"
    
    # Process endpoints
    while IFS= read -r line; do
        method=$(echo "$line" | cut -d' ' -f1)
        path=$(echo "$line" | cut -d' ' -f2-)
        
        # Get description if available
        desc=$(jq -r ".paths[\"$path\"][\"${method,,}\"].summary // .paths[\"$path\"][\"${method,,}\"].description // \"\"" "$SWAGGER_SPEC" 2>/dev/null || echo "")
        
        # Skip if path requires path parameters (we can't test those easily)
        if [[ "$path" == *"{"* ]]; then
            echo -e "${YELLOW}Skipping ${method} ${path} (has path parameters)${NC}"
            continue
        fi
        
        test_endpoint "$method" "$path" "$desc"
        sleep 0.1  # Small delay to avoid overwhelming the server
    done < "$TMP_ENDPOINTS"
    
    rm -f "$TMP_ENDPOINTS"
else
    echo -e "${YELLOW}⚠️  No Swagger spec, testing common endpoints manually...${NC}"
    
    # Test common endpoints manually
    test_endpoint "GET" "/health" "Health check"
    test_endpoint "GET" "/auth/me" "Get current user"
    test_endpoint "GET" "/tracks" "List tracks"
    test_endpoint "GET" "/playlists" "List playlists"
    test_endpoint "GET" "/users" "List users"
fi

# Generate summary
echo ""
echo -e "${BLUE}📊 Generating summary...${NC}"

# Count formats
wrapped_count=$(echo "$RESULTS" | jq '[.[] | select(.format == "wrapped")] | length')
direct_count=$(echo "$RESULTS" | jq '[.[] | select(.format == "direct" or .format == "direct_data")] | length')
auth_required=$(echo "$RESULTS" | jq '[.[] | select(.format == "auth_required")] | length')
error_count=$(echo "$RESULTS" | jq '[.[] | select(.format == "error" or .format == "not_found")] | length')

# Create summary
SUMMARY=$(jq -n \
    --argjson results "$RESULTS" \
    --arg wrapped "$wrapped_count" \
    --arg direct "$direct_count" \
    --arg auth "$auth_required" \
    --arg errors "$error_count" \
    '{
        summary: {
            total_tested: ($results | length),
            wrapped_format: ($wrapped | tonumber),
            direct_format: ($direct | tonumber),
            auth_required: ($auth | tonumber),
            errors: ($errors | tonumber)
        },
        endpoints: $results
    }')

# Save to file
echo "$SUMMARY" | jq '.' > "$OUTPUT_FILE"

echo ""
echo -e "${GREEN}✅ Testing complete!${NC}"
echo -e "${GREEN}Results saved to: ${OUTPUT_FILE}${NC}"
echo ""
echo -e "${BLUE}Summary:${NC}"
echo -e "  Wrapped format (✅): ${wrapped_count}"
echo -e "  Direct format (⚠️):  ${direct_count}"
echo -e "  Auth required (🔒):  ${auth_required}"
echo -e "  Errors (❌):         ${error_count}"

# List inconsistent endpoints
if [ "$direct_count" -gt 0 ]; then
    echo ""
    echo -e "${YELLOW}⚠️  Endpoints with direct format (inconsistent):${NC}"
    echo "$RESULTS" | jq -r '.[] | select(.format == "direct" or .format == "direct_data") | "  \(.method) \(.path)"'
fi
