#!/usr/bin/env bash
# Verify Deployment Script
# Comprehensive verification of all deployed components

set -euo pipefail


# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/init.sh"
SCRIPT_NAME="verify-deployment.sh"
SCRIPT_DESC="Run verification checks for deployed infrastructure and contracts"
SCRIPT_USAGE="${SCRIPT_NAME} [--fast] [--verbose] [--help]"
SCRIPT_OPTIONS="--fast             Skip long-running checks\n--verbose          Verbose logging\n--help             Show help"
SCRIPT_REQUIREMENTS="Azure CLI, jq, access to cluster contexts"
handle_help "${1:-}"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Load .env via dotenv (RPC CR/LF trim). Fallback: raw source.
if [[ -f "$SCRIPT_DIR/../lib/deployment/dotenv.sh" ]]; then
  # shellcheck disable=SC1090
  source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
  load_deployment_env --repo-root "${PROJECT_ROOT:-$REPO_ROOT}"
elif [[ -n "${PROJECT_ROOT:-}" && -f "$PROJECT_ROOT/.env" ]]; then
  set -a
  # shellcheck disable=SC1090
  source "$PROJECT_ROOT/.env"
  set +a
elif [[ -n "${REPO_ROOT:-}" && -f "$REPO_ROOT/.env" ]]; then
  set -a
  # shellcheck disable=SC1090
  source "$REPO_ROOT/.env"
  set +a
fi
CONTRACT_ADDRESSES_FILE="${PROJECT_ROOT}/contracts-deployed.json"

# Load environment variables
if [ -f "${PROJECT_ROOT}/.env" ]; then
    set -a
    source "${PROJECT_ROOT}/.env"
    set +a
fi

RPC_URL="${RPC_URL:-https://rpc.d-bis.org}"
EXPLORER_URL="${EXPLORER_URL:-https://explorer.d-bis.org}"

# Logging function
log() {
    log_success "[$(date +'%Y-%m-%d %H:%M:%S')] $1"
}

error() {
    log_error "[ERROR] $1"
    return 1
}

warn() {
    log_warn "[WARNING] $1"
}

info() {
    log_info "[INFO] $1"
}

# Test RPC endpoint
test_rpc() {
    log "Testing RPC endpoint: $RPC_URL"
    
    local response=$(curl -s -X POST "$RPC_URL" \
        -H "Content-Type: application/json" \
        -d '{
            "jsonrpc":"2.0",
            "method":"eth_blockNumber",
            "params":[],
            "id":1
        }' 2>&1)
    
    if echo "$response" | jq -e '.result' > /dev/null 2>&1; then
        local block_number=$(echo "$response" | jq -r '.result')
        log "RPC endpoint is accessible - Current block: $block_number"
        return 0
    else
        error "RPC endpoint is not accessible: $response"
        return 1
    fi
}

# Test Blockscout explorer
test_blockscout() {
    log "Testing Blockscout explorer: $EXPLORER_URL"
    
    local status_code=$(curl -s -o /dev/null -w "%{http_code}" "$EXPLORER_URL" || echo "000")
    
    if [ "$status_code" = "200" ]; then
        log "Blockscout explorer is accessible (HTTP $status_code)"
        return 0
    else
        warn "Blockscout explorer returned HTTP $status_code (may still be starting)"
        return 1
    fi
}

# Test contract deployment
test_contracts() {
    log "Testing deployed contracts..."
    
    if [ ! -f "$CONTRACT_ADDRESSES_FILE" ]; then
        warn "Contract addresses file not found: $CONTRACT_ADDRESSES_FILE"
        return 1
    fi
    
    local contracts_verified=0
    local contracts_total=0
    
    # Test WETH
    local weth_address=$(jq -r '.weth // empty' "$CONTRACT_ADDRESSES_FILE")
    if [ -n "$weth_address" ] && [ "$weth_address" != "null" ]; then
        contracts_total=$((contracts_total + 1))
        if command -v cast &> /dev/null; then
            local code=$(cast code "$weth_address" --rpc-url "$RPC_URL" 2>/dev/null || echo "0x")
            if [ "$code" != "0x" ] && [ ${#code} -gt 2 ]; then
                log "WETH contract verified at: $weth_address"
                contracts_verified=$((contracts_verified + 1))
            else
                warn "WETH contract code not found at: $weth_address"
            fi
        else
            warn "cast not installed, skipping contract verification"
        fi
    fi
    
    # Test Multicall
    local multicall_address=$(jq -r '.multicall // empty' "$CONTRACT_ADDRESSES_FILE")
    if [ -n "$multicall_address" ] && [ "$multicall_address" != "null" ]; then
        contracts_total=$((contracts_total + 1))
        if command -v cast &> /dev/null; then
            local code=$(cast code "$multicall_address" --rpc-url "$RPC_URL" 2>/dev/null || echo "0x")
            if [ "$code" != "0x" ] && [ ${#code} -gt 2 ]; then
                log "Multicall contract verified at: $multicall_address"
                contracts_verified=$((contracts_verified + 1))
            else
                warn "Multicall contract code not found at: $multicall_address"
            fi
        fi
    fi
    
    # Test Oracle
    local oracle_address=$(jq -r '.oracle // empty' "$CONTRACT_ADDRESSES_FILE")
    if [ -n "$oracle_address" ] && [ "$oracle_address" != "null" ]; then
        contracts_total=$((contracts_total + 1))
        if command -v cast &> /dev/null; then
            local code=$(cast code "$oracle_address" --rpc-url "$RPC_URL" 2>/dev/null || echo "0x")
            if [ "$code" != "0x" ] && [ ${#code} -gt 2 ]; then
                log "Oracle contract verified at: $oracle_address"
                contracts_verified=$((contracts_verified + 1))
            else
                warn "Oracle contract code not found at: $oracle_address"
            fi
        fi
    fi
    
    if [ $contracts_total -gt 0 ]; then
        log "Contracts verified: $contracts_verified/$contracts_total"
        if [ $contracts_verified -eq $contracts_total ]; then
            return 0
        else
            return 1
        fi
    else
        warn "No contracts found in contract addresses file"
        return 1
    fi
}

# Test Kubernetes resources
test_kubernetes() {
    log "Testing Kubernetes resources..."
    
    if ! command -v kubectl &> /dev/null; then
        warn "kubectl not installed, skipping Kubernetes tests"
        return 1
    fi
    
    # Check namespace
    if kubectl get namespace besu-network &> /dev/null; then
        log "Namespace 'besu-network' exists"
    else
        error "Namespace 'besu-network' not found"
        return 1
    fi
    
    # Check RPC pods
    local rpc_pods=$(kubectl get pods -n besu-network -l component=rpc --no-headers 2>/dev/null | wc -l)
    if [ "$rpc_pods" -gt 0 ]; then
        log "RPC pods: $rpc_pods"
        
        # Check if pods are ready
        local ready_pods=$(kubectl get pods -n besu-network -l component=rpc --no-headers 2>/dev/null | grep -c "Running" || echo "0")
        if [ "$ready_pods" -eq "$rpc_pods" ]; then
            log "All RPC pods are running"
        else
            warn "Some RPC pods are not running: $ready_pods/$rpc_pods"
        fi
    else
        warn "No RPC pods found"
    fi
    
    # Check Blockscout pods
    local blockscout_pods=$(kubectl get pods -n besu-network -l app=blockscout --no-headers 2>/dev/null | wc -l)
    if [ "$blockscout_pods" -gt 0 ]; then
        log "Blockscout pods: $blockscout_pods"
    else
        warn "No Blockscout pods found"
    fi
    
    return 0
}

# Test MetaMask integration
test_metamask() {
    log "Testing MetaMask integration..."
    
    # Check network metadata file
    local network_metadata="${PROJECT_ROOT}/metamask/network-metadata.json"
    if [ -f "$network_metadata" ]; then
        if jq empty "$network_metadata" 2>/dev/null; then
            log "Network metadata file is valid"
        else
            error "Network metadata file is invalid"
            return 1
        fi
    else
        error "Network metadata file not found: $network_metadata"
        return 1
    fi
    
    # Check token list file
    local token_list="${PROJECT_ROOT}/metamask/token-list.json"
    if [ -f "$token_list" ]; then
        if jq empty "$token_list" 2>/dev/null; then
            log "Token list file is valid"
            
            # Check if tokens have valid addresses
            local token_count=$(jq '.tokens | length' "$token_list")
            log "Token list contains $token_count tokens"
            
            # Check if WETH address is set
            local weth_address=$(jq -r '.tokens[0].address // empty' "$token_list")
            if [ -n "$weth_address" ] && [ "$weth_address" != "0x0000000000000000000000000000000000000000" ]; then
                log "WETH address is set in token list: $weth_address"
            else
                warn "WETH address is not set in token list"
            fi
        else
            error "Token list file is invalid"
            return 1
        fi
    else
        error "Token list file not found: $token_list"
        return 1
    fi
    
    return 0
}

# Test DNS configuration
test_dns() {
    log "Testing DNS configuration..."
    
    local domains=(
        "d-bis.org"
        "rpc.d-bis.org"
        "rpc2.d-bis.org"
        "explorer.d-bis.org"
    )
    
    local dns_verified=0
    local dns_total=${#domains[@]}
    
    for domain in "${domains[@]}"; do
        info "Checking DNS for: $domain"
        local ip=$(dig +short "$domain" A | head -n 1 || echo "")
        if [ -n "$ip" ]; then
            log "DNS resolved for $domain: $ip"
            dns_verified=$((dns_verified + 1))
        else
            warn "DNS not resolved for $domain"
        fi
    done
    
    log "DNS resolution: $dns_verified/$dns_total domains"
    if [ $dns_verified -eq $dns_total ]; then
        return 0
    else
        return 1
    fi
}

# Generate verification report
generate_report() {
    log "Generating verification report..."
    
    local report_file="${PROJECT_ROOT}/deployment-verification-report.md"
    local timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
    
    cat > "$report_file" <<EOF
# Deployment Verification Report

Generated: $timestamp

## Test Results

### RPC Endpoint
- **URL**: $RPC_URL
- **Status**: $(test_rpc && echo "✅ PASS" || echo "❌ FAIL")

### Blockscout Explorer
- **URL**: $EXPLORER_URL
- **Status**: $(test_blockscout && echo "✅ PASS" || echo "❌ FAIL")

### Contracts
- **Status**: $(test_contracts && echo "✅ PASS" || echo "❌ FAIL")
- **Addresses File**: $CONTRACT_ADDRESSES_FILE

### Kubernetes Resources
- **Status**: $(test_kubernetes && echo "✅ PASS" || echo "❌ FAIL")

### MetaMask Integration
- **Status**: $(test_metamask && echo "✅ PASS" || echo "❌ FAIL")

### DNS Configuration
- **Status**: $(test_dns && echo "✅ PASS" || echo "❌ FAIL")

## Next Steps

1. Fix any failed tests
2. Re-run verification: ./scripts/deployment/verify-deployment.sh
3. Proceed with Ethereum-Lists PR submission
4. Proceed with token list submissions
EOF

    log "Verification report generated: $report_file"
}

# Main function
main() {
    log "Starting deployment verification..."
    
    local tests_passed=0
    local tests_total=6
    
    # Run tests
    test_rpc && tests_passed=$((tests_passed + 1)) || true
    test_blockscout && tests_passed=$((tests_passed + 1)) || true
    test_contracts && tests_passed=$((tests_passed + 1)) || true
    test_kubernetes && tests_passed=$((tests_passed + 1)) || true
    test_metamask && tests_passed=$((tests_passed + 1)) || true
    test_dns && tests_passed=$((tests_passed + 1)) || true
    
    # Generate report
    generate_report
    
    # Summary
    log "Verification completed: $tests_passed/$tests_total tests passed"
    
    if [ $tests_passed -eq $tests_total ]; then
        log "All tests passed! Deployment is ready."
        return 0
    else
        warn "Some tests failed. See deployment-verification-report.md for details."
        return 1
    fi
}

# Run main function
main "$@"

