#!/bin/bash
#===============================================================================
# GALA-SEC-2: Authorization Exploits (IDOR & Privilege Escalation)
#===============================================================================
# Adversarial Security Tests for GALA Event API
#
# Attack Vectors:
#   - IDOR (Insecure Direct Object Reference)
#   - Privilege Escalation (Vertical & Horizontal)
#   - Mass Assignment
#
# Usage:
#   ./tests/Security/adversarial_authz_tests.sh [OPTIONS]
#
# Options:
#   --api-base=URL   API base URL (default: http://localhost:8000/api)
#   --verbose        Show request/response details
#   --output=FILE    Output results to file
#
# Prerequisites:
#   - curl, jq installed
#   - API server running
#   - Test database with sample data
#
# Created: 2026-01-20
# Story: GALA-SEC-2
# Epic: GALA-SEC
#===============================================================================

set -euo pipefail

# ANSI color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Configuration
API_BASE="${API_BASE:-http://localhost:8000/api}"
VERBOSE="${VERBOSE:-false}"
OUTPUT_FILE="${OUTPUT_FILE:-/tmp/adversarial_authz_results_$(date +%Y%m%d_%H%M%S).txt}"

# Test counters
TESTS_PASSED=0
TESTS_FAILED=0
TESTS_SKIPPED=0
VULNERABILITIES_FOUND=0

# Test credentials (should exist in test DB)
CUSTOMER_A_EMAIL="test.customer.a@example.com"
CUSTOMER_A_PASSWORD="TestPassword123!"
CUSTOMER_B_EMAIL="test.customer.b@example.com"
CUSTOMER_B_PASSWORD="TestPassword123!"
ADMIN_EMAIL="test.admin@example.com"
ADMIN_PASSWORD="AdminPassword123!"

# Tokens (populated during setup)
CUSTOMER_A_TOKEN=""
CUSTOMER_B_TOKEN=""
ADMIN_TOKEN=""

#===============================================================================
# Helper Functions
#===============================================================================

log_info() {
    echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$OUTPUT_FILE"
}

log_success() {
    echo -e "${GREEN}[PASS]${NC} $1" | tee -a "$OUTPUT_FILE"
    ((TESTS_PASSED++))
}

log_failure() {
    echo -e "${RED}[FAIL]${NC} $1" | tee -a "$OUTPUT_FILE"
    ((TESTS_FAILED++))
}

log_vuln() {
    echo -e "${RED}[VULN]${NC} $1" | tee -a "$OUTPUT_FILE"
    ((VULNERABILITIES_FOUND++))
}

log_warning() {
    echo -e "${YELLOW}[WARN]${NC} $1" | tee -a "$OUTPUT_FILE"
}

log_skip() {
    echo -e "${YELLOW}[SKIP]${NC} $1" | tee -a "$OUTPUT_FILE"
    ((TESTS_SKIPPED++))
}

log_verbose() {
    if [[ "$VERBOSE" == "true" ]]; then
        echo -e "${YELLOW}[DEBUG]${NC} $1" | tee -a "$OUTPUT_FILE"
    fi
}

# Make HTTP request and capture response
# Returns: HTTP status code
# Sets: RESPONSE_BODY, RESPONSE_STATUS
make_request() {
    local method="$1"
    local endpoint="$2"
    local data="${3:-}"
    local token="${4:-}"

    local headers=(-H "Content-Type: application/json" -H "Accept: application/json")

    if [[ -n "$token" ]]; then
        headers+=(-H "Authorization: Bearer $token")
    fi

    local curl_cmd="curl -s -w '%{http_code}' -X $method"

    if [[ -n "$data" ]]; then
        curl_cmd="$curl_cmd -d '$data'"
    fi

    log_verbose "Request: $method $API_BASE$endpoint"
    log_verbose "Data: $data"

    local response
    if [[ -n "$data" ]]; then
        response=$(curl -s -w '%{http_code}' -X "$method" "${headers[@]}" -d "$data" "$API_BASE$endpoint" 2>/dev/null || echo "000")
    else
        response=$(curl -s -w '%{http_code}' -X "$method" "${headers[@]}" "$API_BASE$endpoint" 2>/dev/null || echo "000")
    fi

    RESPONSE_STATUS="${response: -3}"
    RESPONSE_BODY="${response%???}"

    log_verbose "Response Status: $RESPONSE_STATUS"
    log_verbose "Response Body: $RESPONSE_BODY"

    echo "$RESPONSE_STATUS"
}

# Check if response status is in expected list
check_status() {
    local actual="$1"
    shift
    local expected=("$@")

    for status in "${expected[@]}"; do
        if [[ "$actual" == "$status" ]]; then
            return 0
        fi
    done
    return 1
}

#===============================================================================
# Setup Functions
#===============================================================================

setup_test_environment() {
    log_info "=========================================="
    log_info "GALA-SEC-2: Authorization Exploits Test"
    log_info "=========================================="
    log_info "API Base: $API_BASE"
    log_info "Output File: $OUTPUT_FILE"
    log_info "Started: $(date)"
    log_info ""

    # Check API availability
    log_info "Checking API availability..."
    local health_status
    health_status=$(curl -s -o /dev/null -w '%{http_code}' "$API_BASE/../health" 2>/dev/null || echo "000")

    if [[ "$health_status" == "000" ]]; then
        log_failure "API is not accessible at $API_BASE"
        exit 1
    fi
    log_success "API is accessible (health check: $health_status)"
}

obtain_test_tokens() {
    log_info ""
    log_info "Obtaining test tokens..."

    # Customer A token
    log_info "Authenticating Customer A ($CUSTOMER_A_EMAIL)..."
    make_request "POST" "/login" "{\"email\":\"$CUSTOMER_A_EMAIL\",\"password\":\"$CUSTOMER_A_PASSWORD\"}" ""

    if [[ "$RESPONSE_STATUS" == "200" ]]; then
        CUSTOMER_A_TOKEN=$(echo "$RESPONSE_BODY" | jq -r '.data.access_token // .access_token // empty' 2>/dev/null || echo "")
        if [[ -n "$CUSTOMER_A_TOKEN" && "$CUSTOMER_A_TOKEN" != "null" ]]; then
            log_success "Customer A authenticated"
        else
            log_warning "Customer A token extraction failed - will create test account"
            create_test_customer "A" "$CUSTOMER_A_EMAIL" "$CUSTOMER_A_PASSWORD"
        fi
    else
        log_warning "Customer A login failed ($RESPONSE_STATUS) - will create test account"
        create_test_customer "A" "$CUSTOMER_A_EMAIL" "$CUSTOMER_A_PASSWORD"
    fi

    # Customer B token
    log_info "Authenticating Customer B ($CUSTOMER_B_EMAIL)..."
    make_request "POST" "/login" "{\"email\":\"$CUSTOMER_B_EMAIL\",\"password\":\"$CUSTOMER_B_PASSWORD\"}" ""

    if [[ "$RESPONSE_STATUS" == "200" ]]; then
        CUSTOMER_B_TOKEN=$(echo "$RESPONSE_BODY" | jq -r '.data.access_token // .access_token // empty' 2>/dev/null || echo "")
        if [[ -n "$CUSTOMER_B_TOKEN" && "$CUSTOMER_B_TOKEN" != "null" ]]; then
            log_success "Customer B authenticated"
        else
            log_warning "Customer B token extraction failed - will create test account"
            create_test_customer "B" "$CUSTOMER_B_EMAIL" "$CUSTOMER_B_PASSWORD"
        fi
    else
        log_warning "Customer B login failed ($RESPONSE_STATUS) - will create test account"
        create_test_customer "B" "$CUSTOMER_B_EMAIL" "$CUSTOMER_B_PASSWORD"
    fi

    # Admin token
    log_info "Authenticating Admin ($ADMIN_EMAIL)..."
    make_request "POST" "/admin/login" "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASSWORD\"}" ""

    if [[ "$RESPONSE_STATUS" == "200" ]]; then
        ADMIN_TOKEN=$(echo "$RESPONSE_BODY" | jq -r '.data.access_token // .access_token // .token // empty' 2>/dev/null || echo "")
        if [[ -n "$ADMIN_TOKEN" && "$ADMIN_TOKEN" != "null" ]]; then
            log_success "Admin authenticated"
        else
            log_warning "Admin token extraction failed - admin tests will be skipped"
        fi
    else
        log_warning "Admin login failed ($RESPONSE_STATUS) - admin tests will be limited"
    fi

    log_info ""
}

create_test_customer() {
    local label="$1"
    local email="$2"
    local password="$3"

    log_info "Creating test Customer $label..."
    make_request "POST" "/register" "{\"first_name\":\"Test\",\"last_name\":\"Customer$label\",\"email\":\"$email\",\"password\":\"$password\",\"password_confirmation\":\"$password\"}" ""

    if [[ "$RESPONSE_STATUS" == "201" || "$RESPONSE_STATUS" == "200" ]]; then
        local token
        token=$(echo "$RESPONSE_BODY" | jq -r '.data.access_token // .access_token // empty' 2>/dev/null || echo "")
        if [[ "$label" == "A" ]]; then
            CUSTOMER_A_TOKEN="$token"
        else
            CUSTOMER_B_TOKEN="$token"
        fi
        log_success "Customer $label created and authenticated"
    else
        log_warning "Failed to create Customer $label ($RESPONSE_STATUS)"
    fi
}

#===============================================================================
# IDOR Tests
#===============================================================================

run_idor_tests() {
    log_info ""
    log_info "=========================================="
    log_info "1. IDOR (Insecure Direct Object Reference) Tests"
    log_info "=========================================="

    test_idor_order_access
    test_idor_order_enumeration
    test_idor_ticket_download
    test_idor_profile_access
}

test_idor_order_access() {
    log_info ""
    log_info "1.1 Testing IDOR: Access other users' orders via ID manipulation"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    # Try to access orders 1-10 (likely to exist in test DB)
    local idor_found=false
    for order_id in 1 2 3 999 "abc" "../admin"; do
        log_verbose "Attempting to access order: $order_id"

        make_request "GET" "/orders/$order_id" "" "$CUSTOMER_A_TOKEN"

        # Successful IDOR if we get 200 with order data that doesn't belong to us
        if [[ "$RESPONSE_STATUS" == "200" ]]; then
            local order_email
            order_email=$(echo "$RESPONSE_BODY" | jq -r '.data.customer_email // .customer_email // empty' 2>/dev/null || echo "")

            if [[ -n "$order_email" && "$order_email" != "$CUSTOMER_A_EMAIL" ]]; then
                log_vuln "IDOR VULNERABILITY: Accessed order $order_id belonging to $order_email"
                idor_found=true
            fi
        fi
    done

    if [[ "$idor_found" == "false" ]]; then
        log_success "IDOR order access properly blocked (401/403/404 returned)"
    fi
}

test_idor_order_enumeration() {
    log_info ""
    log_info "1.2 Testing IDOR: Order enumeration via sequential IDs"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    local accessible_count=0
    local blocked_count=0

    # Try 20 sequential order IDs
    for order_id in $(seq 1 20); do
        make_request "GET" "/orders/$order_id" "" "$CUSTOMER_A_TOKEN"

        if [[ "$RESPONSE_STATUS" == "200" ]]; then
            ((accessible_count++))
        elif check_status "$RESPONSE_STATUS" "401" "403" "404"; then
            ((blocked_count++))
        fi
    done

    log_info "Enumeration results: $accessible_count accessible, $blocked_count blocked"

    # If we can access more than 5 orders (unlikely for a single customer), flag as potential issue
    if [[ $accessible_count -gt 5 ]]; then
        log_warning "High number of accessible orders ($accessible_count) - verify authorization"
    else
        log_success "Order enumeration properly restricted"
    fi
}

test_idor_ticket_download() {
    log_info ""
    log_info "1.3 Testing IDOR: Download other customers' tickets"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    # Try to download tickets for orders that don't belong to us
    local vulnerable=false
    for order_id in 1 2 3 "test-session-id-123"; do
        make_request "GET" "/customer/orders/$order_id/tickets/download" "" "$CUSTOMER_A_TOKEN"

        # If we get 200 with PDF content, check if it's actually our order
        if [[ "$RESPONSE_STATUS" == "200" ]]; then
            # Check content type (should be PDF or error)
            log_warning "Received 200 for order $order_id - verify authorization"
        fi
    done

    if [[ "$vulnerable" == "false" ]]; then
        log_success "Ticket download properly protected (requires ownership)"
    fi
}

test_idor_profile_access() {
    log_info ""
    log_info "1.4 Testing IDOR: Access other customers' profile data"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    # Try to access profile data via various endpoints
    # Test user ID manipulation
    for user_id in 1 2 3 999; do
        make_request "GET" "/users/$user_id" "" "$CUSTOMER_A_TOKEN"

        if [[ "$RESPONSE_STATUS" == "200" ]]; then
            local profile_email
            profile_email=$(echo "$RESPONSE_BODY" | jq -r '.data.email // .email // empty' 2>/dev/null || echo "")

            if [[ -n "$profile_email" && "$profile_email" != "$CUSTOMER_A_EMAIL" ]]; then
                log_vuln "IDOR VULNERABILITY: Accessed profile of $profile_email via user ID $user_id"
            fi
        fi
    done

    # /me endpoint should only return current user's data
    make_request "GET" "/me" "" "$CUSTOMER_A_TOKEN"

    if [[ "$RESPONSE_STATUS" == "200" ]]; then
        local me_email
        me_email=$(echo "$RESPONSE_BODY" | jq -r '.data.user.email // .data.email // .email // empty' 2>/dev/null || echo "")

        if [[ "$me_email" == "$CUSTOMER_A_EMAIL" ]]; then
            log_success "/me endpoint returns only authenticated user's data"
        else
            log_warning "/me returned unexpected email: $me_email"
        fi
    fi
}

#===============================================================================
# Vertical Privilege Escalation Tests
#===============================================================================

run_vertical_escalation_tests() {
    log_info ""
    log_info "=========================================="
    log_info "2. Vertical Privilege Escalation Tests"
    log_info "=========================================="
    log_info "(Customer attempting to access Admin routes)"

    test_customer_admin_routes
    test_customer_create_events
    test_customer_modify_capacity
    test_customer_scanner_access
}

test_customer_admin_routes() {
    log_info ""
    log_info "2.1 Testing: Customer accessing admin routes"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    local admin_routes=(
        "/admin/events"
        "/admin/orders"
        "/admin/customers"
        "/admin/users"
        "/admin/settings"
        "/admin/roles"
        "/admin/tickets"
        "/admin/me"
    )

    local blocked_count=0
    local vulnerable_count=0

    for route in "${admin_routes[@]}"; do
        make_request "GET" "$route" "" "$CUSTOMER_A_TOKEN"

        if check_status "$RESPONSE_STATUS" "401" "403"; then
            ((blocked_count++))
            log_verbose "Admin route $route properly blocked ($RESPONSE_STATUS)"
        elif [[ "$RESPONSE_STATUS" == "200" ]]; then
            log_vuln "PRIVILEGE ESCALATION: Customer accessed admin route $route"
            ((vulnerable_count++))
        else
            log_verbose "Admin route $route returned unexpected status: $RESPONSE_STATUS"
            ((blocked_count++))  # Non-200 responses are considered blocked
        fi
    done

    if [[ $vulnerable_count -eq 0 ]]; then
        log_success "All admin routes properly blocked for customers ($blocked_count routes tested)"
    fi
}

test_customer_create_events() {
    log_info ""
    log_info "2.2 Testing: Customer creating events (admin-only)"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    local event_data='{"name":"Hacker Event","start_date":"2026-12-31","start_time":"19:00","venue_id":1}'

    make_request "POST" "/admin/events" "$event_data" "$CUSTOMER_A_TOKEN"

    if check_status "$RESPONSE_STATUS" "401" "403"; then
        log_success "Event creation properly blocked for customers ($RESPONSE_STATUS)"
    elif [[ "$RESPONSE_STATUS" == "201" || "$RESPONSE_STATUS" == "200" ]]; then
        log_vuln "PRIVILEGE ESCALATION: Customer was able to create event!"
    else
        log_success "Event creation blocked (status: $RESPONSE_STATUS)"
    fi
}

test_customer_modify_capacity() {
    log_info ""
    log_info "2.3 Testing: Customer modifying event capacity (admin-only)"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    # Try to modify event capacity
    local capacity_data='{"capacity":99999,"max_tickets_per_order":999}'

    make_request "PUT" "/admin/events/1" "$capacity_data" "$CUSTOMER_A_TOKEN"

    if check_status "$RESPONSE_STATUS" "401" "403"; then
        log_success "Event modification properly blocked for customers ($RESPONSE_STATUS)"
    elif [[ "$RESPONSE_STATUS" == "200" ]]; then
        log_vuln "PRIVILEGE ESCALATION: Customer was able to modify event capacity!"
    else
        log_success "Event modification blocked (status: $RESPONSE_STATUS)"
    fi
}

test_customer_scanner_access() {
    log_info ""
    log_info "2.4 Testing: Customer accessing scanner stats (admin-only)"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    local scanner_routes=(
        "/admin/scanner/stats"
        "/admin/scanner/zones"
        "/admin/scanner/activity"
        "/admin/events/1/scanner-stats"
    )

    local blocked=0
    for route in "${scanner_routes[@]}"; do
        make_request "GET" "$route" "" "$CUSTOMER_A_TOKEN"

        if check_status "$RESPONSE_STATUS" "401" "403" "404"; then
            ((blocked++))
        elif [[ "$RESPONSE_STATUS" == "200" ]]; then
            log_vuln "PRIVILEGE ESCALATION: Customer accessed scanner route $route"
        fi
    done

    if [[ $blocked -eq ${#scanner_routes[@]} ]]; then
        log_success "Scanner routes properly blocked for customers"
    fi
}

#===============================================================================
# Horizontal Privilege Escalation Tests
#===============================================================================

run_horizontal_escalation_tests() {
    log_info ""
    log_info "=========================================="
    log_info "3. Horizontal Privilege Escalation Tests"
    log_info "=========================================="
    log_info "(User A attempting to access User B's data)"

    test_customer_a_access_customer_b_orders
    test_customer_a_modify_customer_b_order
    test_customer_a_view_customer_b_bookings
}

test_customer_a_access_customer_b_orders() {
    log_info ""
    log_info "3.1 Testing: Customer A accessing Customer B's orders"

    if [[ -z "$CUSTOMER_A_TOKEN" || -z "$CUSTOMER_B_TOKEN" ]]; then
        log_skip "Both customer tokens required"
        return
    fi

    # First, get Customer B's orders
    make_request "GET" "/orders" "" "$CUSTOMER_B_TOKEN"

    if [[ "$RESPONSE_STATUS" == "200" ]]; then
        local customer_b_orders
        customer_b_orders=$(echo "$RESPONSE_BODY" | jq -r '.data.orders[0].order_id // empty' 2>/dev/null || echo "")

        if [[ -n "$customer_b_orders" && "$customer_b_orders" != "null" ]]; then
            log_verbose "Customer B has order: $customer_b_orders"

            # Now try to access that order as Customer A
            make_request "GET" "/orders/$customer_b_orders" "" "$CUSTOMER_A_TOKEN"

            if [[ "$RESPONSE_STATUS" == "200" ]]; then
                log_vuln "HORIZONTAL ESCALATION: Customer A accessed Customer B's order $customer_b_orders"
            else
                log_success "Customer A blocked from accessing Customer B's order ($RESPONSE_STATUS)"
            fi
        else
            log_info "Customer B has no orders to test with"
        fi
    else
        log_info "Could not retrieve Customer B's orders"
    fi
}

test_customer_a_modify_customer_b_order() {
    log_info ""
    log_info "3.2 Testing: Customer A modifying Customer B's order"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    # Try to modify an order that doesn't belong to Customer A
    local modification_data='{"customer_name":"Hacked Name"}'

    for order_id in 1 2 3; do
        make_request "PUT" "/orders/$order_id" "$modification_data" "$CUSTOMER_A_TOKEN"

        if [[ "$RESPONSE_STATUS" == "200" ]]; then
            log_vuln "HORIZONTAL ESCALATION: Customer A modified order $order_id"
        fi
    done

    log_success "Order modification properly protected"
}

test_customer_a_view_customer_b_bookings() {
    log_info ""
    log_info "3.3 Testing: Customer A viewing Customer B's booking history"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    # Try to access booking history via various paths
    local vulnerable=false

    # Try scan history for orders that don't belong to Customer A
    for order_id in 1 2 3; do
        make_request "GET" "/customer/orders/$order_id/scan-history" "" "$CUSTOMER_A_TOKEN"

        if [[ "$RESPONSE_STATUS" == "200" ]]; then
            local has_data
            has_data=$(echo "$RESPONSE_BODY" | jq -r '.data | length // 0' 2>/dev/null || echo "0")

            if [[ "$has_data" -gt 0 ]]; then
                log_warning "Customer A received scan history for order $order_id - verify ownership"
            fi
        fi
    done

    if [[ "$vulnerable" == "false" ]]; then
        log_success "Booking history properly protected"
    fi
}

#===============================================================================
# Mass Assignment Tests
#===============================================================================

run_mass_assignment_tests() {
    log_info ""
    log_info "=========================================="
    log_info "4. Mass Assignment Tests"
    log_info "=========================================="

    test_mass_assignment_registration
    test_mass_assignment_profile_update
    test_mass_assignment_booking
}

test_mass_assignment_registration() {
    log_info ""
    log_info "4.1 Testing: Mass assignment on registration"

    local malicious_data='{
        "first_name": "Hacker",
        "last_name": "User",
        "email": "mass.assignment.test.'$(date +%s)'@example.com",
        "password": "TestPassword123!",
        "password_confirmation": "TestPassword123!",
        "is_admin": true,
        "role": "admin",
        "entry_type": "admin",
        "is_active": true,
        "permissions": ["*"]
    }'

    make_request "POST" "/register" "$malicious_data" ""

    if [[ "$RESPONSE_STATUS" == "201" || "$RESPONSE_STATUS" == "200" ]]; then
        # Check if admin fields were accepted
        local entry_type
        entry_type=$(echo "$RESPONSE_BODY" | jq -r '.data.user.entry_type // empty' 2>/dev/null || echo "")

        if [[ "$entry_type" == "admin" ]]; then
            log_vuln "MASS ASSIGNMENT: entry_type=admin accepted on registration!"
        else
            log_success "Mass assignment blocked - entry_type defaulted to customer"
        fi

        # Check for is_admin field
        local is_admin
        is_admin=$(echo "$RESPONSE_BODY" | jq -r '.data.user.is_admin // empty' 2>/dev/null || echo "")

        if [[ "$is_admin" == "true" || "$is_admin" == "1" ]]; then
            log_vuln "MASS ASSIGNMENT: is_admin=true accepted on registration!"
        fi
    else
        log_info "Registration returned $RESPONSE_STATUS (may have validation errors)"
    fi
}

test_mass_assignment_profile_update() {
    log_info ""
    log_info "4.2 Testing: Mass assignment on profile update"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    local malicious_profile='{
        "first_name": "Updated",
        "is_admin": true,
        "role": "admin",
        "entry_type": "admin",
        "status": "admin",
        "permissions": ["*", "admin.*"]
    }'

    make_request "PUT" "/profile" "$malicious_profile" "$CUSTOMER_A_TOKEN"

    if [[ "$RESPONSE_STATUS" == "200" ]]; then
        # Verify the user's actual status
        make_request "GET" "/me" "" "$CUSTOMER_A_TOKEN"

        local entry_type
        entry_type=$(echo "$RESPONSE_BODY" | jq -r '.data.user.entry_type // empty' 2>/dev/null || echo "")

        if [[ "$entry_type" == "admin" ]]; then
            log_vuln "MASS ASSIGNMENT: entry_type escalated to admin via profile update!"
        else
            log_success "Mass assignment blocked on profile update"
        fi
    else
        log_success "Profile update with malicious fields rejected ($RESPONSE_STATUS)"
    fi
}

test_mass_assignment_booking() {
    log_info ""
    log_info "4.3 Testing: Mass assignment on booking"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    # Try to inject discount or price override via booking
    local malicious_booking='{
        "event_id": 1,
        "seat_ids": ["test-seat-1"],
        "session_id": "test-session-'$(date +%s)'",
        "discount": 100,
        "total_override": 0.01,
        "is_comp": true,
        "price_override": 0
    }'

    make_request "POST" "/seats/hold" "$malicious_booking" "$CUSTOMER_A_TOKEN"

    if [[ "$RESPONSE_STATUS" == "200" || "$RESPONSE_STATUS" == "201" ]]; then
        # Check if malicious fields were accepted
        local total
        total=$(echo "$RESPONSE_BODY" | jq -r '.data.total // .total // empty' 2>/dev/null || echo "")

        if [[ -n "$total" && "$total" == "0" || "$total" == "0.01" ]]; then
            log_vuln "MASS ASSIGNMENT: Price override accepted on booking!"
        else
            log_success "Mass assignment fields ignored on booking"
        fi
    else
        log_success "Booking with malicious fields handled ($RESPONSE_STATUS)"
    fi
}

#===============================================================================
# Additional Bypass Tests
#===============================================================================

run_bypass_tests() {
    log_info ""
    log_info "=========================================="
    log_info "5. Additional Authorization Bypass Tests"
    log_info "=========================================="

    test_token_manipulation
    test_parameter_pollution
    test_path_traversal_auth
}

test_token_manipulation() {
    log_info ""
    log_info "5.1 Testing: JWT token manipulation"

    # Test with invalid/malformed tokens
    local invalid_tokens=(
        "invalid-token"
        "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo5OTk5fQ.invalid"
        "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyX2lkIjoxLCJyb2xlIjoiYWRtaW4ifQ."
        ""
        "null"
        "undefined"
    )

    local blocked=0
    for token in "${invalid_tokens[@]}"; do
        make_request "GET" "/me" "" "$token"

        if check_status "$RESPONSE_STATUS" "401" "403"; then
            ((blocked++))
        elif [[ "$RESPONSE_STATUS" == "200" ]]; then
            log_vuln "TOKEN BYPASS: Invalid token '$token' returned 200"
        fi
    done

    log_success "Invalid tokens properly rejected ($blocked tokens tested)"
}

test_parameter_pollution() {
    log_info ""
    log_info "5.2 Testing: HTTP parameter pollution for auth bypass"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    # Try parameter pollution on order access
    # Note: This tests if duplicate params can confuse authorization
    make_request "GET" "/orders/1?user_id=999&user_id=1" "" "$CUSTOMER_A_TOKEN"

    if [[ "$RESPONSE_STATUS" == "200" ]]; then
        log_warning "Parameter pollution test returned 200 - verify authorization"
    else
        log_success "Parameter pollution did not bypass authorization ($RESPONSE_STATUS)"
    fi
}

test_path_traversal_auth() {
    log_info ""
    log_info "5.3 Testing: Path traversal for auth bypass"

    if [[ -z "$CUSTOMER_A_TOKEN" ]]; then
        log_skip "Customer A token not available"
        return
    fi

    local traversal_paths=(
        "/orders/../admin/events"
        "/orders/1/../../../admin/me"
        "/me/../../admin/users"
        "/admin/../../../me"
    )

    local blocked=0
    for path in "${traversal_paths[@]}"; do
        make_request "GET" "$path" "" "$CUSTOMER_A_TOKEN"

        if check_status "$RESPONSE_STATUS" "401" "403" "404"; then
            ((blocked++))
        elif [[ "$RESPONSE_STATUS" == "200" ]]; then
            log_warning "Path traversal '$path' returned 200 - verify response"
        fi
    done

    log_success "Path traversal attempts handled ($blocked paths tested)"
}

#===============================================================================
# Report Generation
#===============================================================================

generate_report() {
    log_info ""
    log_info "=========================================="
    log_info "GALA-SEC-2: Authorization Exploits - RESULTS"
    log_info "=========================================="

    local total_tests=$((TESTS_PASSED + TESTS_FAILED + TESTS_SKIPPED))

    echo "" | tee -a "$OUTPUT_FILE"
    echo "============================================" | tee -a "$OUTPUT_FILE"
    echo "SUMMARY" | tee -a "$OUTPUT_FILE"
    echo "============================================" | tee -a "$OUTPUT_FILE"
    echo "Total Tests: $total_tests" | tee -a "$OUTPUT_FILE"
    echo -e "${GREEN}Passed: $TESTS_PASSED${NC}" | tee -a "$OUTPUT_FILE"
    echo -e "${RED}Failed: $TESTS_FAILED${NC}" | tee -a "$OUTPUT_FILE"
    echo -e "${YELLOW}Skipped: $TESTS_SKIPPED${NC}" | tee -a "$OUTPUT_FILE"
    echo "" | tee -a "$OUTPUT_FILE"

    if [[ $VULNERABILITIES_FOUND -gt 0 ]]; then
        echo -e "${RED}CRITICAL: $VULNERABILITIES_FOUND VULNERABILITIES FOUND!${NC}" | tee -a "$OUTPUT_FILE"
    else
        echo -e "${GREEN}NO CRITICAL VULNERABILITIES FOUND${NC}" | tee -a "$OUTPUT_FILE"
    fi

    echo "" | tee -a "$OUTPUT_FILE"
    echo "Completed: $(date)" | tee -a "$OUTPUT_FILE"
    echo "Results saved to: $OUTPUT_FILE" | tee -a "$OUTPUT_FILE"

    # Exit with appropriate code
    if [[ $VULNERABILITIES_FOUND -gt 0 ]]; then
        exit 1
    elif [[ $TESTS_FAILED -gt 0 ]]; then
        exit 2
    else
        exit 0
    fi
}

#===============================================================================
# Main Execution
#===============================================================================

parse_args() {
    for arg in "$@"; do
        case $arg in
            --api-base=*)
                API_BASE="${arg#*=}"
                ;;
            --verbose)
                VERBOSE="true"
                ;;
            --output=*)
                OUTPUT_FILE="${arg#*=}"
                ;;
            --help)
                echo "Usage: $0 [OPTIONS]"
                echo ""
                echo "Options:"
                echo "  --api-base=URL   API base URL (default: http://localhost:8000/api)"
                echo "  --verbose        Show request/response details"
                echo "  --output=FILE    Output results to file"
                echo ""
                exit 0
                ;;
        esac
    done
}

main() {
    parse_args "$@"

    # Clear output file
    : > "$OUTPUT_FILE"

    # Run test suite
    setup_test_environment
    obtain_test_tokens

    run_idor_tests
    run_vertical_escalation_tests
    run_horizontal_escalation_tests
    run_mass_assignment_tests
    run_bypass_tests

    generate_report
}

main "$@"
