#!/usr/bin/env bash
# ============================================================
# QualityMax Security Scan — Open Source Edition
# https://qualitymax.io/security-scan
#
# A zero-dependency security scanner for web applications.
# Checks for exposed secrets, missing headers, injection
# vectors, signup abuse resistance, and common misconfigs.
#
# Usage:
#   curl -sL https://qualitymax.io/security-scan | bash -s -- https://your-site.com
#   # or download and run:
#   chmod +x security-scan.sh
#   ./security-scan.sh https://your-site.com
#
# Options:
#   --full          Run all checks including slow ones
#   --json          Output results as JSON
#   --signup URL    Test signup endpoint for abuse resistance
#   --no-color      Disable colored output
#   --timeout N     HTTP timeout in seconds (default: 10)
#
# License: MIT
# Copyright (c) 2026 QualityMax / Ruslan Strazhnyk
# ============================================================

set -euo pipefail

VERSION="1.0.0"
TIMEOUT=10
COLOR=true
FULL=false
JSON=false
SIGNUP_URL=""
TARGET=""

# Counters
TOTAL=0
PASSED=0
FAILED=0
WARNINGS=0
CRITICAL=0

# ── Colors ────────────────────────────────────────────────────

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
PURPLE='\033[0;35m'
WHITE='\033[1;37m'
DIM='\033[0;90m'
NC='\033[0m'

no_color() {
    RED=''; GREEN=''; YELLOW=''; CYAN=''; PURPLE=''; WHITE=''; DIM=''; NC=''
}

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

banner() {
    echo ""
    echo -e "${PURPLE}  ┌─────────────────────────────────────────┐${NC}"
    echo -e "${PURPLE}  │${WHITE}   QualityMax Security Scan v${VERSION}        ${PURPLE}│${NC}"
    echo -e "${PURPLE}  │${DIM}   Open source web security scanner      ${PURPLE}│${NC}"
    echo -e "${PURPLE}  │${DIM}   https://qualitymax.io                 ${PURPLE}│${NC}"
    echo -e "${PURPLE}  └─────────────────────────────────────────┘${NC}"
    echo ""
}

usage() {
    echo "Usage: $0 [OPTIONS] <URL>"
    echo ""
    echo "Options:"
    echo "  --full          Run all checks including slow ones"
    echo "  --json          Output results as JSON"
    echo "  --signup URL    Test signup endpoint for abuse resistance"
    echo "  --no-color      Disable colored output"
    echo "  --timeout N     HTTP timeout in seconds (default: 10)"
    echo "  -h, --help      Show this help"
    echo ""
    echo "Examples:"
    echo "  $0 https://myapp.com"
    echo "  $0 --full --signup /api/auth/signup https://myapp.com"
    echo "  $0 --json https://myapp.com > report.json"
    exit 0
}

log_pass() {
    TOTAL=$((TOTAL + 1))
    PASSED=$((PASSED + 1))
    if [ "$JSON" = false ]; then
        echo -e "  ${GREEN}PASS${NC}  $1"
    fi
}

log_fail() {
    local severity="${2:-HIGH}"
    TOTAL=$((TOTAL + 1))
    FAILED=$((FAILED + 1))
    if [ "$severity" = "CRITICAL" ]; then
        CRITICAL=$((CRITICAL + 1))
    fi
    if [ "$JSON" = false ]; then
        echo -e "  ${RED}FAIL${NC}  ${RED}[$severity]${NC} $1"
    fi
}

log_warn() {
    TOTAL=$((TOTAL + 1))
    WARNINGS=$((WARNINGS + 1))
    if [ "$JSON" = false ]; then
        echo -e "  ${YELLOW}WARN${NC}  $1"
    fi
}

log_skip() {
    if [ "$JSON" = false ]; then
        echo -e "  ${DIM}SKIP${NC}  $1"
    fi
}

log_section() {
    if [ "$JSON" = false ]; then
        echo ""
        echo -e "${CYAN}── $1 ──${NC}"
    fi
}

# Fetch URL and store headers + body
fetch() {
    local url="$1"
    curl -sS -L --max-time "$TIMEOUT" \
        -D /dev/stderr \
        -o /dev/stdout \
        -A "QualityMax-SecurityScan/${VERSION}" \
        "$url" 2>/tmp/qm_headers
    return $?
}

fetch_headers_only() {
    local url="$1"
    curl -sS -I -L --max-time "$TIMEOUT" \
        -A "QualityMax-SecurityScan/${VERSION}" \
        "$url" 2>/dev/null
}

# ── Parse Args ────────────────────────────────────────────────

while [[ $# -gt 0 ]]; do
    case $1 in
        --full) FULL=true; shift ;;
        --json) JSON=true; COLOR=false; no_color; shift ;;
        --signup) SIGNUP_URL="$2"; shift 2 ;;
        --no-color) COLOR=false; no_color; shift ;;
        --timeout) TIMEOUT="$2"; shift 2 ;;
        -h|--help) usage ;;
        -*) echo "Unknown option: $1"; usage ;;
        *) TARGET="$1"; shift ;;
    esac
done

if [ -z "$TARGET" ]; then
    banner
    echo -e "${RED}Error:${NC} No target URL provided."
    echo ""
    usage
fi

# Strip trailing slash
TARGET="${TARGET%/}"

if [ "$JSON" = false ]; then
    banner
    echo -e "${WHITE}Target:${NC} $TARGET"
    echo -e "${DIM}Started: $(date -u '+%Y-%m-%d %H:%M:%S UTC')${NC}"
fi

# ── Verify target is reachable ────────────────────────────────

HTTP_CODE=$(curl -sS -o /dev/null -w '%{http_code}' --max-time "$TIMEOUT" "$TARGET" 2>/dev/null || echo "000")
if [ "$HTTP_CODE" = "000" ]; then
    echo -e "${RED}Error:${NC} Cannot reach $TARGET (timeout: ${TIMEOUT}s)"
    exit 1
fi

# ═══════════════════════════════════════════════════════════════
# 1. SECURITY HEADERS
# ═══════════════════════════════════════════════════════════════

log_section "Security Headers"

HEADERS=$(fetch_headers_only "$TARGET")
HEADERS_LOWER=$(echo "$HEADERS" | tr '[:upper:]' '[:lower:]')

# Content-Security-Policy
if echo "$HEADERS_LOWER" | grep -q "content-security-policy:"; then
    log_pass "Content-Security-Policy header present"
else
    log_fail "Missing Content-Security-Policy header" "HIGH"
fi

# Strict-Transport-Security
if echo "$HEADERS_LOWER" | grep -q "strict-transport-security:"; then
    log_pass "Strict-Transport-Security (HSTS) header present"
else
    log_fail "Missing Strict-Transport-Security header" "HIGH"
fi

# X-Content-Type-Options
if echo "$HEADERS_LOWER" | grep -q "x-content-type-options:.*nosniff"; then
    log_pass "X-Content-Type-Options: nosniff"
else
    log_warn "Missing X-Content-Type-Options: nosniff header"
fi

# X-Frame-Options
if echo "$HEADERS_LOWER" | grep -q "x-frame-options:"; then
    log_pass "X-Frame-Options header present (clickjacking protection)"
else
    log_warn "Missing X-Frame-Options header"
fi

# Referrer-Policy
if echo "$HEADERS_LOWER" | grep -q "referrer-policy:"; then
    log_pass "Referrer-Policy header present"
else
    log_warn "Missing Referrer-Policy header"
fi

# Permissions-Policy
if echo "$HEADERS_LOWER" | grep -q "permissions-policy:"; then
    log_pass "Permissions-Policy header present"
else
    log_warn "Missing Permissions-Policy header"
fi

# Server header leaks version info
if echo "$HEADERS_LOWER" | grep -qE "^server:.*[0-9]+\.[0-9]+"; then
    SERVER_VER=$(echo "$HEADERS" | grep -i "^server:" | head -1 | sed 's/^[Ss]erver: *//')
    log_fail "Server header leaks version: $SERVER_VER" "MEDIUM"
else
    log_pass "Server header does not leak version info"
fi

# X-Powered-By
if echo "$HEADERS_LOWER" | grep -q "x-powered-by:"; then
    POWERED=$(echo "$HEADERS" | grep -i "^x-powered-by:" | head -1 | sed 's/^[Xx]-[Pp]owered-[Bb]y: *//')
    log_fail "X-Powered-By header exposes technology: $POWERED" "MEDIUM"
else
    log_pass "No X-Powered-By header (technology not exposed)"
fi

# ═══════════════════════════════════════════════════════════════
# 2. EXPOSED SECRETS IN CLIENT CODE
# ═══════════════════════════════════════════════════════════════

log_section "Exposed Secrets"

PAGE_SOURCE=$(curl -sS -L --max-time "$TIMEOUT" "$TARGET" 2>/dev/null || echo "")

check_secret() {
    local name="$1"
    local pattern="$2"
    local severity="${3:-CRITICAL}"
    if echo "$PAGE_SOURCE" | grep -qE "$pattern"; then
        log_fail "$name found in page source" "$severity"
    else
        log_pass "No $name in page source"
    fi
}

check_secret "Stripe secret key"       "sk_live_[a-zA-Z0-9]{24,}"
check_secret "Stripe webhook secret"   "whsec_[a-zA-Z0-9]{24,}"
check_secret "OpenAI API key"          "sk-proj-[a-zA-Z0-9]{20,}"
check_secret "Anthropic API key"       "sk-ant-api[0-9]{2}-[a-zA-Z0-9_-]{20,}"
check_secret "AWS access key"          "AKIA[A-Z0-9]{16}"
check_secret "AWS secret key"          "aws_secret_access_key"         "CRITICAL"
check_secret "Database URL with creds" "postgresql://[^:]+:[^@]+@"     "CRITICAL"
check_secret "SendGrid API key"        "SG\.[a-zA-Z0-9_-]{22,}"
check_secret "Supabase service role"   "service_role"                  "HIGH"
check_secret "JWT secret"              "jwt[_-]?secret"                "HIGH"
check_secret "Private key"             "PRIVATE KEY-----"                 "CRITICAL"
check_secret "Google API key"          "AIza[0-9A-Za-z_-]{35}"        "HIGH"
check_secret "GitHub token"            "gh[ps]_[A-Za-z0-9_]{36,}"     "CRITICAL"
check_secret "Slack token"             "xox[bpors]-[0-9]+"            "HIGH"

# Check common JS config paths
for js_path in "/js/config.js" "/config.js" "/js/app.js" "/static/js/config.js" "/env.js" "/.env" "/.env.local"; do
    JS_RESP=$(curl -sS -o /dev/null -w '%{http_code}' --max-time "$TIMEOUT" "${TARGET}${js_path}" 2>/dev/null || echo "000")
    if [ "$JS_RESP" = "200" ]; then
        JS_CONTENT=$(curl -sS -L --max-time "$TIMEOUT" "${TARGET}${js_path}" 2>/dev/null || echo "")
        if echo "$JS_CONTENT" | grep -qEi "(sk_live_|sk-proj-|AKIA|service_role|-----BEGIN|password.*[:=].*['\"][^'\"]{8,})"; then
            log_fail "Secrets detected in ${js_path}" "CRITICAL"
        fi
        if [ "$js_path" = "/.env" ] || [ "$js_path" = "/.env.local" ]; then
            log_fail "Environment file accessible: ${js_path}" "CRITICAL"
        fi
    fi
done

# ═══════════════════════════════════════════════════════════════
# 3. COMMON ENDPOINTS & MISCONFIGS
# ═══════════════════════════════════════════════════════════════

log_section "Endpoint Security"

# Admin panel accessible without auth
for admin_path in "/admin" "/admin.html" "/admin/" "/dashboard" "/_admin" "/wp-admin"; do
    ADMIN_CODE=$(curl -sS -o /dev/null -w '%{http_code}' --max-time "$TIMEOUT" "${TARGET}${admin_path}" 2>/dev/null || echo "000")
    if [ "$ADMIN_CODE" = "200" ]; then
        log_fail "Admin panel accessible without auth: ${admin_path}" "CRITICAL"
    fi
done

# Debug endpoints
for debug_path in "/debug" "/_debug" "/debug/vars" "/actuator" "/actuator/env" "/__debug__" "/server-info" "/phpinfo.php"; do
    DEBUG_CODE=$(curl -sS -o /dev/null -w '%{http_code}' --max-time "$TIMEOUT" "${TARGET}${debug_path}" 2>/dev/null || echo "000")
    if [ "$DEBUG_CODE" = "200" ]; then
        log_fail "Debug endpoint accessible: ${debug_path}" "HIGH"
    fi
done

# API docs exposure
for docs_path in "/docs" "/swagger" "/swagger-ui" "/redoc" "/api-docs" "/graphql"; do
    DOCS_CODE=$(curl -sS -o /dev/null -w '%{http_code}' --max-time "$TIMEOUT" "${TARGET}${docs_path}" 2>/dev/null || echo "000")
    if [ "$DOCS_CODE" = "200" ]; then
        log_warn "API documentation publicly accessible: ${docs_path}"
    fi
done

# Source maps
if echo "$PAGE_SOURCE" | grep -qE '\.js\.map|sourceMappingURL'; then
    log_warn "Source maps detected (may expose original source code)"
else
    log_pass "No source maps exposed"
fi

# Debug mode indicators
if echo "$PAGE_SOURCE" | grep -qEi '(debug.*true|DEBUG.*=.*1|debugMode.*enabled)'; then
    log_fail "Debug mode appears to be enabled" "HIGH"
else
    log_pass "No debug mode indicators found"
fi

# ═══════════════════════════════════════════════════════════════
# 4. XSS & INJECTION VECTORS
# ═══════════════════════════════════════════════════════════════

log_section "Injection Resistance"

# Inline event handlers
INLINE_HANDLERS=$(echo "$PAGE_SOURCE" | grep -coE 'on(click|error|load|mouseover)=' || echo "0")
if [ "$INLINE_HANDLERS" -gt 5 ]; then
    log_warn "Found $INLINE_HANDLERS inline event handlers (prefer addEventListener)"
else
    log_pass "Minimal inline event handlers ($INLINE_HANDLERS found)"
fi

# innerHTML usage
INNERHTML=$(echo "$PAGE_SOURCE" | grep -coE '\.innerHTML\s*=' || echo "0")
if [ "$INNERHTML" -gt 0 ]; then
    log_warn "Found $INNERHTML innerHTML assignments (potential DOM XSS)"
else
    log_pass "No innerHTML assignments detected"
fi

# eval() usage
if echo "$PAGE_SOURCE" | grep -qE '[^a-zA-Z]eval\s*\('; then
    log_fail "eval() detected in client code (code injection risk)" "HIGH"
else
    log_pass "No eval() calls detected"
fi

# document.write usage
if echo "$PAGE_SOURCE" | grep -qE 'document\.write\s*\('; then
    log_warn "document.write() detected (potential XSS vector)"
else
    log_pass "No document.write() calls detected"
fi

# Third-party scripts without SRI
EXTERNAL_SCRIPTS=$(echo "$PAGE_SOURCE" | grep -oE '<script[^>]+src="https?://[^"]+' | grep -v 'integrity=' || echo "")
EXTERNAL_COUNT=$(echo "$EXTERNAL_SCRIPTS" | grep -c "src=" 2>/dev/null || echo "0")
if [ "$EXTERNAL_COUNT" -gt 0 ]; then
    log_warn "$EXTERNAL_COUNT external scripts loaded without SRI integrity check"
else
    log_pass "All external scripts have integrity checks (or none loaded)"
fi

# CSRF tokens on forms
FORM_COUNT=$(echo "$PAGE_SOURCE" | grep -cE '<form' 2>/dev/null || echo "0")
FORM_COUNT=$(echo "$FORM_COUNT" | tr -d '[:space:]')
CSRF_COUNT=$(echo "$PAGE_SOURCE" | grep -ciE 'csrf|_token|csrfmiddlewaretoken' 2>/dev/null || echo "0")
CSRF_COUNT=$(echo "$CSRF_COUNT" | tr -d '[:space:]')
if [ "$FORM_COUNT" -gt 0 ] && [ "$CSRF_COUNT" -eq 0 ]; then
    log_warn "Found $FORM_COUNT form(s) with no CSRF token references"
elif [ "$FORM_COUNT" -gt 0 ]; then
    log_pass "Forms appear to have CSRF protection"
fi

# ═══════════════════════════════════════════════════════════════
# 5. SIGNUP / AUTH ABUSE RESISTANCE
# ═══════════════════════════════════════════════════════════════

if [ -n "$SIGNUP_URL" ]; then
    log_section "Signup Abuse Resistance"

    # Normalize signup URL
    if [[ "$SIGNUP_URL" == /* ]]; then
        SIGNUP_FULL="${TARGET}${SIGNUP_URL}"
    else
        SIGNUP_FULL="$SIGNUP_URL"
    fi

    # Test 1: Missing fields should return 422, not 500
    MISSING_CODE=$(curl -sS -o /dev/null -w '%{http_code}' --max-time "$TIMEOUT" \
        -X POST -H "Content-Type: application/json" \
        -d '{"email":"test@test.com"}' \
        "$SIGNUP_FULL" 2>/dev/null || echo "000")
    if [ "$MISSING_CODE" = "500" ]; then
        log_fail "Missing fields return 500 (should be 422)" "HIGH"
    elif [ "$MISSING_CODE" = "422" ] || [ "$MISSING_CODE" = "400" ]; then
        log_pass "Missing fields properly rejected ($MISSING_CODE)"
    else
        log_warn "Missing fields returned $MISSING_CODE (expected 400/422)"
    fi

    # Test 2: SQL injection in email
    SQL_CODE=$(curl -sS -o /tmp/qm_sql_resp -w '%{http_code}' --max-time "$TIMEOUT" \
        -X POST -H "Content-Type: application/json" \
        -d '{"email":"admin'\''--@evil.com","password":"Test123!@#","first_name":"x","last_name":"x"}' \
        "$SIGNUP_FULL" 2>/dev/null || echo "000")
    SQL_BODY=$(cat /tmp/qm_sql_resp 2>/dev/null || echo "")
    if [ "$SQL_CODE" = "500" ]; then
        log_fail "SQL injection payload returned 500" "CRITICAL"
    elif echo "$SQL_BODY" | grep -qiE "(syntax error|select|table|column)"; then
        log_fail "SQL error details leaked in response" "CRITICAL"
    else
        log_pass "SQL injection payload handled safely ($SQL_CODE)"
    fi

    # Test 3: XSS in name fields
    XSS_CODE=$(curl -sS -o /tmp/qm_xss_resp -w '%{http_code}' --max-time "$TIMEOUT" \
        -X POST -H "Content-Type: application/json" \
        -d '{"email":"xss@gmail.com","password":"Test123!@#","first_name":"<script>alert(1)</script>","last_name":"test"}' \
        "$SIGNUP_FULL" 2>/dev/null || echo "000")
    XSS_BODY=$(cat /tmp/qm_xss_resp 2>/dev/null || echo "")
    if echo "$XSS_BODY" | grep -q "<script>"; then
        log_fail "XSS payload reflected in response" "CRITICAL"
    else
        log_pass "XSS payload not reflected in response"
    fi

    # Test 4: Disposable email rejection
    DISP_CODE=$(curl -sS -o /tmp/qm_disp_resp -w '%{http_code}' --max-time "$TIMEOUT" \
        -X POST -H "Content-Type: application/json" \
        -d '{"email":"test@mailinator.com","password":"Test123!@#","first_name":"test","last_name":"test"}' \
        "$SIGNUP_FULL" 2>/dev/null || echo "000")
    if [ "$DISP_CODE" = "400" ] || [ "$DISP_CODE" = "403" ] || [ "$DISP_CODE" = "429" ]; then
        log_pass "Disposable email (mailinator.com) rejected ($DISP_CODE)"
    elif [ "$DISP_CODE" = "200" ]; then
        log_warn "Disposable email (mailinator.com) accepted — consider blocking"
    fi

    # Test 5: Rate limiting on rapid requests
    if [ "$FULL" = true ]; then
        RATE_LIMITED=false
        for i in $(seq 1 8); do
            RL_CODE=$(curl -sS -o /dev/null -w '%{http_code}' --max-time "$TIMEOUT" \
                -X POST -H "Content-Type: application/json" \
                -d "{\"email\":\"ratetest${i}@gmail.com\",\"password\":\"Test123!@#\",\"first_name\":\"rate\",\"last_name\":\"test\"}" \
                "$SIGNUP_FULL" 2>/dev/null || echo "000")
            if [ "$RL_CODE" = "429" ] || [ "$RL_CODE" = "403" ]; then
                RATE_LIMITED=true
                break
            fi
        done
        if [ "$RATE_LIMITED" = true ]; then
            log_pass "Rate limiting triggered after rapid signups"
        else
            log_fail "No rate limiting detected after 8 rapid signups" "HIGH"
        fi
    else
        log_skip "Rate limiting test (use --full to enable)"
    fi

    # Test 6: Honeypot detection
    HP_CODE=$(curl -sS -o /tmp/qm_hp_resp -w '%{http_code}' --max-time "$TIMEOUT" \
        -X POST -H "Content-Type: application/json" \
        -d '{"email":"bot@test.com","password":"Test123!@#","first_name":"bot","last_name":"test","website":"http://spam.com"}' \
        "$SIGNUP_FULL" 2>/dev/null || echo "000")
    HP_BODY=$(cat /tmp/qm_hp_resp 2>/dev/null || echo "")
    if [ "$HP_CODE" = "200" ] && echo "$HP_BODY" | grep -qi "success"; then
        log_pass "Honeypot field returns fake success (bot trapped)"
    else
        log_warn "Honeypot field not detected (consider adding one)"
    fi

    # Test 7: Error sanitization
    ERR_CODE=$(curl -sS -o /tmp/qm_err_resp -w '%{http_code}' --max-time "$TIMEOUT" \
        -X POST -H "Content-Type: application/json" \
        -d '{"email":null,"password":null}' \
        "$SIGNUP_FULL" 2>/dev/null || echo "000")
    ERR_BODY=$(cat /tmp/qm_err_resp 2>/dev/null || echo "")
    if echo "$ERR_BODY" | grep -qiE "(traceback|site-packages|\.py\"|/usr/)"; then
        log_fail "Stack trace or internal paths leaked in error response" "HIGH"
    else
        log_pass "Error responses do not leak internal details"
    fi

    # Cleanup
    rm -f /tmp/qm_sql_resp /tmp/qm_xss_resp /tmp/qm_disp_resp /tmp/qm_hp_resp /tmp/qm_err_resp
fi

# ═══════════════════════════════════════════════════════════════
# 6. SSL/TLS CHECK
# ═══════════════════════════════════════════════════════════════

if [[ "$TARGET" == https://* ]]; then
    log_section "SSL/TLS"

    # Certificate expiry
    CERT_EXPIRY=$(echo | openssl s_client -servername "$(echo "$TARGET" | sed 's|https://||;s|/.*||')" \
        -connect "$(echo "$TARGET" | sed 's|https://||;s|/.*||'):443" 2>/dev/null | \
        openssl x509 -noout -enddate 2>/dev/null | sed 's/notAfter=//' || echo "")

    if [ -n "$CERT_EXPIRY" ]; then
        CERT_EPOCH=$(date -j -f "%b %d %T %Y %Z" "$CERT_EXPIRY" "+%s" 2>/dev/null || \
                     date -d "$CERT_EXPIRY" "+%s" 2>/dev/null || echo "0")
        NOW_EPOCH=$(date "+%s")
        DAYS_LEFT=$(( (CERT_EPOCH - NOW_EPOCH) / 86400 ))
        if [ "$DAYS_LEFT" -lt 0 ]; then
            log_fail "SSL certificate has EXPIRED" "CRITICAL"
        elif [ "$DAYS_LEFT" -lt 14 ]; then
            log_warn "SSL certificate expires in $DAYS_LEFT days"
        else
            log_pass "SSL certificate valid ($DAYS_LEFT days remaining)"
        fi
    fi

    # HTTP to HTTPS redirect
    if [[ "$TARGET" == https://* ]]; then
        HTTP_URL=$(echo "$TARGET" | sed 's|^https://|http://|')
        REDIRECT_LOC=$(curl -sS -o /dev/null -w '%{redirect_url}' --max-time "$TIMEOUT" "$HTTP_URL" 2>/dev/null || echo "")
        if [[ "$REDIRECT_LOC" == https://* ]]; then
            log_pass "HTTP redirects to HTTPS"
        else
            log_warn "HTTP does not redirect to HTTPS"
        fi
    fi
fi

# ═══════════════════════════════════════════════════════════════
# RESULTS
# ═══════════════════════════════════════════════════════════════

if [ "$JSON" = true ]; then
    cat <<JSONEOF
{
  "scanner": "QualityMax Security Scan",
  "version": "$VERSION",
  "target": "$TARGET",
  "timestamp": "$(date -u '+%Y-%m-%dT%H:%M:%SZ')",
  "summary": {
    "total": $TOTAL,
    "passed": $PASSED,
    "failed": $FAILED,
    "warnings": $WARNINGS,
    "critical": $CRITICAL
  },
  "verdict": "$([ $CRITICAL -gt 0 ] && echo "CRITICAL" || ([ $FAILED -gt 0 ] && echo "FAIL" || echo "PASS"))"
}
JSONEOF
else
    echo ""
    echo -e "${CYAN}── Results ──${NC}"
    echo ""
    echo -e "  ${WHITE}Total:${NC}    $TOTAL checks"
    echo -e "  ${GREEN}Passed:${NC}   $PASSED"
    echo -e "  ${RED}Failed:${NC}   $FAILED"
    echo -e "  ${YELLOW}Warnings:${NC} $WARNINGS"

    if [ $CRITICAL -gt 0 ]; then
        echo ""
        echo -e "  ${RED}CRITICAL: $CRITICAL critical issue(s) found${NC}"
        echo -e "  ${RED}Your application has severe security vulnerabilities.${NC}"
    elif [ $FAILED -gt 0 ]; then
        echo ""
        echo -e "  ${YELLOW}$FAILED issue(s) need attention.${NC}"
    else
        echo ""
        echo -e "  ${GREEN}No critical issues found.${NC}"
    fi

    echo ""
    echo -e "${DIM}──────────────────────────────────────────────${NC}"
    echo -e "${DIM}Full security audit: https://qualitymax.io${NC}"
    echo -e "${DIM}Blog: https://qualitymax.io/blog${NC}"
    echo ""
fi

# Cleanup
rm -f /tmp/qm_headers

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