#!/bin/bash

# End-to-End Test for explorer.d-bis.org
# Comprehensive testing of all explorer functionality

set -uo pipefail

EXPLORER_URL="https://explorer.d-bis.org"
BASE_URL="http://192.168.11.140"
TEST_RESULTS=()
PASSED=0
FAILED=0
WARNINGS=0

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

log_test() {
    local status=$1
    local message=$2
    if [ "$status" = "PASS" ]; then
        echo -e "${GREEN}✅ PASS${NC}: $message"
        ((PASSED++))
        TEST_RESULTS+=("PASS: $message")
    elif [ "$status" = "FAIL" ]; then
        echo -e "${RED}❌ FAIL${NC}: $message"
        ((FAILED++))
        TEST_RESULTS+=("FAIL: $message")
    elif [ "$status" = "WARN" ]; then
        echo -e "${YELLOW}⚠️  WARN${NC}: $message"
        ((WARNINGS++))
        TEST_RESULTS+=("WARN: $message")
    else
        echo -e "${BLUE}ℹ️  INFO${NC}: $message"
    fi
}

test_http_response() {
    local url=$1
    local expected_code=$2
    local description=$3
    
    local response_code=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 10 --max-time 30 "$url" 2>/dev/null || echo "000")
    
    if [ "$response_code" = "$expected_code" ]; then
        log_test "PASS" "$description (HTTP $response_code)"
        return 0
    elif [ "$response_code" = "000" ]; then
        log_test "FAIL" "$description (Connection failed/timeout)"
        return 1
    else
        log_test "FAIL" "$description (Expected HTTP $expected_code, got $response_code)"
        return 1
    fi
}

test_content() {
    local url=$1
    local search_term=$2
    local description=$3
    local extra_opts="${4:-}"
    
    local content=$(curl -s -L --max-redirs 3 $extra_opts --connect-timeout 10 --max-time 30 "$url" 2>/dev/null || echo "")
    
    if [ -z "$content" ]; then
        log_test "FAIL" "$description (Empty response)"
        return 1
    elif grep -qi "$search_term" <<< "$content"; then
        log_test "PASS" "$description (Found: $search_term)"
        return 0
    else
        # Show first 100 chars for debugging
        PREVIEW=$(printf '%.100s' "$content" | tr -d '\n')
        log_test "FAIL" "$description (Not found: $search_term, got: $PREVIEW...)"
        return 1
    fi
}

test_json_response() {
    local url=$1
    local description=$2
    
    local response=$(curl -s -L --connect-timeout 10 --max-time 30 "$url" 2>/dev/null || echo "")
    
    if echo "$response" | jq . >/dev/null 2>&1; then
        log_test "PASS" "$description (Valid JSON)"
        return 0
    else
        log_test "FAIL" "$description (Invalid JSON or empty response)"
        return 1
    fi
}

echo "=========================================="
echo "End-to-End Test: explorer.d-bis.org"
echo "=========================================="
echo "Test URL: $EXPLORER_URL"
echo "Base URL: $BASE_URL"
echo "Date: $(date)"
echo "=========================================="
echo ""

# ============================================
# 1. Basic Connectivity Tests
# ============================================
echo "=== 1. Basic Connectivity Tests ==="

# Test HTTPS accessibility (may fail if Cloudflare tunnel not running)
HTTPS_CODE=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 5 --max-time 10 "$EXPLORER_URL" 2>/dev/null || echo "000")
if [ "$HTTPS_CODE" = "200" ] || [ "$HTTPS_CODE" = "301" ] || [ "$HTTPS_CODE" = "302" ]; then
    log_test "PASS" "HTTPS homepage accessibility (HTTP $HTTPS_CODE)"
elif [ "$HTTPS_CODE" = "000" ]; then
    log_test "WARN" "HTTPS homepage not accessible externally (Cloudflare tunnel may be down - testing internal access instead)"
else
    log_test "WARN" "HTTPS homepage returned HTTP $HTTPS_CODE"
fi

# Test HTTP redirect (301 or 302)
REDIRECT_CODE=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 10 "http://explorer.d-bis.org" 2>/dev/null || echo "000")
if [ "$REDIRECT_CODE" = "301" ] || [ "$REDIRECT_CODE" = "302" ]; then
    log_test "PASS" "HTTP to HTTPS redirect (HTTP $REDIRECT_CODE)"
else
    log_test "FAIL" "HTTP to HTTPS redirect (Expected 301 or 302, got $REDIRECT_CODE)"
fi

# Test direct IP access (internal)
test_http_response "$BASE_URL:80/" "200" "Direct IP access (port 80)"

echo ""

# ============================================
# 2. Frontend Content Tests
# ============================================
echo "=== 2. Frontend Content Tests ==="

# Use internal URL for content tests since HTTPS may not be accessible
CONTENT_URL="$BASE_URL:80"

# Test homepage content
test_content "$CONTENT_URL" "SolaceScanScout" "Homepage contains SolaceScanScout title"

# Test explorer branding
test_content "$CONTENT_URL" "Explorer" "Homepage contains explorer branding"

# Test HTML structure
test_content "$CONTENT_URL" "<!DOCTYPE html" "Valid HTML document structure"

# Test JavaScript loading
test_content "$CONTENT_URL" "ethers" "JavaScript libraries present"

echo ""

# ============================================
# 3. API Endpoint Tests
# ============================================
echo "=== 3. API Endpoint Tests ==="

# Test Blockscout API stats (via internal nginx)
test_json_response "$BASE_URL:80/api/v2/stats" "Blockscout API /api/v2/stats endpoint (via nginx)"

# Test Blockscout API blocks (via internal nginx)
test_json_response "$BASE_URL:80/api/v2/blocks" "Blockscout API /api/v2/blocks endpoint (via nginx)"

# Test Blockscout API transactions (via internal nginx)
test_json_response "$BASE_URL:80/api/v2/transactions" "Blockscout API /api/v2/transactions endpoint (via nginx)"

# Test direct API access (internal)
test_json_response "$BASE_URL:4000/api/v2/stats" "Direct Blockscout API access (port 4000)"

echo ""

# ============================================
# 4. Security & Headers Tests
# ============================================
echo "=== 4. Security & Headers Tests ==="

# Test headers from internal nginx
HEADERS=$(curl -s -I -L --connect-timeout 10 --max-time 30 "$BASE_URL:80/" 2>/dev/null || echo "")

if echo "$HEADERS" | grep -qi "strict-transport-security\|HSTS"; then
    log_test "PASS" "HSTS header present"
else
    log_test "WARN" "HSTS header not found"
fi

if echo "$HEADERS" | grep -qi "x-frame-options"; then
    log_test "PASS" "X-Frame-Options header present"
else
    log_test "WARN" "X-Frame-Options header not found"
fi

if echo "$HEADERS" | grep -qi "x-content-type-options"; then
    log_test "PASS" "X-Content-Type-Options header present"
else
    log_test "WARN" "X-Content-Type-Options header not found"
fi

echo ""

# ============================================
# 5. Performance Tests
# ============================================
echo "=== 5. Performance Tests ==="

# Test performance on internal URL
START_TIME=$(date +%s%N)
curl -s -o /dev/null -w '%{time_total}' --connect-timeout 10 --max-time 30 "$BASE_URL:80/" >/dev/null 2>&1
END_TIME=$(date +%s%N)
RESPONSE_TIME=$(echo "scale=3; ($END_TIME - $START_TIME) / 1000000000" | bc 2>/dev/null || echo "N/A")

if [ "$RESPONSE_TIME" != "N/A" ]; then
    if (( $(echo "$RESPONSE_TIME < 3.0" | bc -l 2>/dev/null || echo 0) )); then
        log_test "PASS" "Response time acceptable (${RESPONSE_TIME}s)"
    else
        log_test "WARN" "Response time slow (${RESPONSE_TIME}s)"
    fi
else
    log_test "WARN" "Could not measure response time"
fi

echo ""

# ============================================
# 6. Service Status Tests
# ============================================
echo "=== 6. Service Status Tests ==="

# Test nginx on VMID 5000
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-02 'pct exec 5000 -- systemctl is-active nginx 2>/dev/null'" 2>/dev/null | grep -q "active"; then
    log_test "PASS" "Nginx service running on VMID 5000"
else
    log_test "FAIL" "Nginx service not running on VMID 5000"
fi

# Test Blockscout service
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-02 'pct exec 5000 -- systemctl is-active blockscout 2>/dev/null || pct exec 5000 -- docker ps | grep -q blockscout'" 2>/dev/null | grep -qE "active|blockscout"; then
    log_test "PASS" "Blockscout service running on VMID 5000"
else
    log_test "WARN" "Blockscout service status unknown"
fi

# Test port 80 listening
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-02 'pct exec 5000 -- ss -tlnp | grep -q :80'" 2>/dev/null; then
    log_test "PASS" "Port 80 listening on VMID 5000"
else
    log_test "FAIL" "Port 80 not listening on VMID 5000"
fi

# Test port 4000 listening
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-02 'pct exec 5000 -- ss -tlnp | grep -q :4000'" 2>/dev/null; then
    log_test "PASS" "Port 4000 listening on VMID 5000"
else
    log_test "WARN" "Port 4000 not listening on VMID 5000"
fi

echo ""

# ============================================
# 7. Frontend Functionality Tests
# ============================================
echo "=== 7. Frontend Functionality Tests ==="

# Check if frontend file exists
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-02 'pct exec 5000 -- test -f /var/www/html/index.html'" 2>/dev/null; then
    log_test "PASS" "Frontend HTML file exists"
else
    log_test "FAIL" "Frontend HTML file not found"
fi

# Check frontend file size (should be substantial)
FRONTEND_SIZE=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-02 'pct exec 5000 -- stat -c%s /var/www/html/index.html 2>/dev/null'" 2>/dev/null || echo "0")
if [ "$FRONTEND_SIZE" -gt 10000 ]; then
    log_test "PASS" "Frontend file size reasonable (${FRONTEND_SIZE} bytes)"
else
    log_test "WARN" "Frontend file size suspiciously small (${FRONTEND_SIZE} bytes)"
fi

echo ""

# ============================================
# 8. Network Routing Tests
# ============================================
echo "=== 8. Network Routing Tests ==="

# Test NPMplus routing (may fail if Cloudflare tunnel down)
NPMPLUS_CHECK=$(curl -s -I --connect-timeout 5 --max-time 10 "https://explorer.d-bis.org" 2>/dev/null | head -1 || echo "")
if echo "$NPMPLUS_CHECK" | grep -qE "200|301|302"; then
    log_test "PASS" "NPMplus routing working"
elif echo "$NPMPLUS_CHECK" | grep -qE "000|timeout"; then
    log_test "WARN" "NPMplus routing timeout (Cloudflare tunnel may be down)"
else
    log_test "WARN" "NPMplus routing returned: $NPMPLUS_CHECK"
fi

# Test DNS resolution
if host explorer.d-bis.org 2>/dev/null | grep -q "has address"; then
    log_test "PASS" "DNS resolution working"
else
    log_test "WARN" "DNS resolution check failed (may be local DNS issue)"
fi

echo ""

# ============================================
# 9. API Data Validation
# ============================================
echo "=== 9. API Data Validation ==="

# Get stats and validate structure (use internal URL)
STATS_JSON=$(curl -s -L --connect-timeout 10 --max-time 30 "$BASE_URL:80/api/v2/stats" 2>/dev/null || echo "{}")

if echo "$STATS_JSON" | jq -e '.total_blocks' >/dev/null 2>&1; then
    TOTAL_BLOCKS=$(echo "$STATS_JSON" | jq -r '.total_blocks // 0')
    if [ "$TOTAL_BLOCKS" -gt 0 ]; then
        log_test "PASS" "API returns valid block count ($TOTAL_BLOCKS blocks)"
    else
        log_test "WARN" "API returns zero blocks (may be indexing)"
    fi
else
    log_test "FAIL" "API stats structure invalid"
fi

# Check for chain ID (optional; Blockscout may use different field)
if echo "$STATS_JSON" | jq -e '.chain_id' >/dev/null 2>&1; then
    CHAIN_ID=$(echo "$STATS_JSON" | jq -r '.chain_id // "unknown"')
    log_test "PASS" "API returns chain ID ($CHAIN_ID)"
elif echo "$STATS_JSON" | jq -e '.total_blocks' >/dev/null 2>&1; then
    log_test "PASS" "API returns stats (chain ID optional)"
else
    log_test "WARN" "API does not return chain ID"
fi

echo ""

# ============================================
# 10. Path-Based URL & Link Tests (SPA routing)
# ============================================
echo "=== 10. Path-Based URL & Link Tests ==="

# Use BASE_URL:80 for path tests (HTTP SPA paths served by nginx)
PATH_TEST_BASE="$BASE_URL:80"
PATH_CURL_EXTRA=""

# SPA serves index.html for all paths - verify path-based routing is present
test_content "$PATH_TEST_BASE/address/0x99b3511a2d315a497c8112c1fdd8d508d4b1e506" "fromPath" "Path-based routing code present (address URL)" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/address/0x99b3511a2d315a497c8112c1fdd8d508d4b1e506" "SolaceScanScout" "Address path serves SPA shell" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/blocks" "SolaceScanScout" "Blocks path serves SPA" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/transactions" "SolaceScanScout" "Transactions path serves SPA" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/bridge" "SolaceScanScout" "Bridge path serves SPA" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/weth" "SolaceScanScout" "WETH path serves SPA" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/watchlist" "SolaceScanScout" "Watchlist path serves SPA" "$PATH_CURL_EXTRA"

# Verify nav links exist in HTML (use same base)
test_content "$PATH_TEST_BASE/" "#/home" "Home nav link present" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/" "#/blocks" "Blocks nav link present" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/" "#/transactions" "Transactions nav link present" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/" "#/bridge" "Bridge nav link present" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/" "#/weth" "WETH nav link present" "$PATH_CURL_EXTRA"
test_content "$PATH_TEST_BASE/" "/snap/" "MetaMask Snap nav link present" "$PATH_CURL_EXTRA"

# Verify applyHashRoute handles pathname
test_content "$PATH_TEST_BASE/" "location.pathname" "Path-based route detection present" "$PATH_CURL_EXTRA"

echo ""

# ============================================
# 11. Error Handling Tests
# ============================================
echo "=== 11. Error Handling Tests ==="

# SPA fallback: unknown paths return index.html (200) or redirect (301/302)
FALLBACK_CODE=$(curl -s -o /dev/null -w '%{http_code}' --max-redirs 2 --connect-timeout 10 "$BASE_URL:80/nonexistent-page" 2>/dev/null || echo "000")
if [ "$FALLBACK_CODE" = "200" ] || [ "$FALLBACK_CODE" = "301" ] || [ "$FALLBACK_CODE" = "302" ]; then
    log_test "PASS" "SPA fallback for unknown paths (HTTP $FALLBACK_CODE)"
else
    log_test "WARN" "SPA fallback returned HTTP $FALLBACK_CODE (expected 200 or redirect)"
fi

# Test API error handling (use internal URL)
API_ERROR=$(curl -s -L --connect-timeout 10 --max-time 30 "$BASE_URL:80/api/v2/invalid-endpoint" 2>/dev/null || echo "")
API_ERROR_CODE=$(curl -s -o /dev/null -w '%{http_code}' -L --connect-timeout 10 --max-time 30 "$BASE_URL:80/api/v2/invalid-endpoint" 2>/dev/null || echo "000")
if [ "$API_ERROR_CODE" = "404" ] || [ "$API_ERROR_CODE" = "400" ] || echo "$API_ERROR" | grep -qiE "error|404|not found"; then
    log_test "PASS" "API error handling works (HTTP $API_ERROR_CODE)"
else
    log_test "WARN" "API error handling unclear (HTTP $API_ERROR_CODE)"
fi

echo ""

# ============================================
# Summary
# ============================================
echo "=========================================="
echo "Test Summary"
echo "=========================================="
echo -e "${GREEN}Passed: $PASSED${NC}"
echo -e "${RED}Failed: $FAILED${NC}"
echo -e "${YELLOW}Warnings: $WARNINGS${NC}"
echo ""

TOTAL=$((PASSED + FAILED + WARNINGS))
if [ $TOTAL -gt 0 ]; then
    PASS_PERCENT=$(echo "scale=1; $PASSED * 100 / $TOTAL" | bc 2>/dev/null || echo "0")
    echo "Pass Rate: ${PASS_PERCENT}%"
fi

echo ""
if [ $FAILED -eq 0 ]; then
    echo -e "${GREEN}✅ All critical tests passed!${NC}"
    exit 0
else
    echo -e "${RED}❌ Some tests failed. Review results above.${NC}"
    exit 1
fi
