#!/usr/bin/env bash
# Node Health Check Script
# Check health of individual Besu nodes

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

source "$PROJECT_ROOT/lib/common.sh"

# Load configuration
load_config

# Parse arguments
VMID="${1:-}"
JSON_OUTPUT="${JSON_OUTPUT:-false}"

if [[ -z "$VMID" ]]; then
    echo "Usage: $0 <VMID> [--json]"
    echo ""
    echo "Checks health of a specific Besu node (container)."
    echo ""
    echo "Options:"
    echo "  --json    Output in JSON format"
    exit 1
fi

if [[ "${2:-}" == "--json" ]] || [[ "${2:-}" == "-j" ]]; then
    JSON_OUTPUT=true
fi

# Health check results
declare -A HEALTH
HEALTH["container_running"]="false"
HEALTH["service_running"]="false"
HEALTH["besu_process"]="false"
HEALTH["p2p_listening"]="false"
HEALTH["rpc_available"]="false"
HEALTH["block_height"]=""
HEALTH["peer_count"]=""
HEALTH["chain_id"]=""
HEALTH["errors"]=()

# Check container status
if pct status "$VMID" 2>/dev/null | grep -q running; then
    HEALTH["container_running"]="true"
else
    HEALTH["errors"]+=("Container $VMID is not running")
    if [[ "$JSON_OUTPUT" == "true" ]]; then
        echo "{\"vmid\":\"$VMID\",\"status\":\"error\",\"container_running\":false,\"errors\":[\"Container $VMID is not running\"]}"
    else
        log_error "Container $VMID is not running"
    fi
    exit 1
fi

# Determine service type
SERVICE_TYPE="unknown"
if pct exec "$VMID" -- systemctl list-units --type=service 2>/dev/null | grep -q "besu-validator.service"; then
    SERVICE_TYPE="validator"
    SERVICE_NAME="besu-validator"
elif pct exec "$VMID" -- systemctl list-units --type=service 2>/dev/null | grep -q "besu-sentry.service"; then
    SERVICE_TYPE="sentry"
    SERVICE_NAME="besu-sentry"
elif pct exec "$VMID" -- systemctl list-units --type=service 2>/dev/null | grep -q "besu-rpc.service"; then
    SERVICE_TYPE="rpc"
    SERVICE_NAME="besu-rpc"
fi

# Check service status
if pct exec "$VMID" -- systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
    HEALTH["service_running"]="true"
fi

# Check Besu process
if pct exec "$VMID" -- pgrep -f "besu" >/dev/null 2>&1; then
    HEALTH["besu_process"]="true"
fi

# Check P2P port (30303)
if pct exec "$VMID" -- netstat -tuln 2>/dev/null | grep -q ":30303" || \
   pct exec "$VMID" -- ss -tuln 2>/dev/null | grep -q ":30303"; then
    HEALTH["p2p_listening"]="true"
fi

# Check RPC (if available)
if pct exec "$VMID" -- curl -s -X POST \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
    http://localhost:8545 2>/dev/null | grep -q "result"; then
    HEALTH["rpc_available"]="true"
    
    # Get block height
    block_height=$(pct exec "$VMID" -- curl -s -X POST \
        -H "Content-Type: application/json" \
        -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
        http://localhost:8545 2>/dev/null | \
        python3 -c "import sys, json; data=json.load(sys.stdin); print(int(data.get('result', '0x0'), 16))" 2>/dev/null || echo "")
    HEALTH["block_height"]="$block_height"
    
    # Get chain ID
    chain_id=$(pct exec "$VMID" -- curl -s -X POST \
        -H "Content-Type: application/json" \
        -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \
        http://localhost:8545 2>/dev/null | \
        python3 -c "import sys, json; data=json.load(sys.stdin); print(int(data.get('result', '0x0'), 16))" 2>/dev/null || echo "")
    HEALTH["chain_id"]="$chain_id"
    
    # Get peer count
    peer_count=$(pct exec "$VMID" -- curl -s -X POST \
        -H "Content-Type: application/json" \
        -d '{"jsonrpc":"2.0","method":"admin_peers","params":[],"id":1}' \
        http://localhost:8545 2>/dev/null | \
        python3 -c "import sys, json; data=json.load(sys.stdin); peers=data.get('result', []); print(len(peers) if isinstance(peers, list) else 0)" 2>/dev/null || echo "0")
    HEALTH["peer_count"]="$peer_count"
fi

# Determine overall status
STATUS="healthy"
if [[ "${HEALTH[container_running]}" != "true" ]] || \
   [[ "${HEALTH[besu_process]}" != "true" ]] || \
   [[ "${HEALTH[p2p_listening]}" != "true" ]]; then
    STATUS="unhealthy"
elif [[ "${HEALTH[service_running]}" != "true" ]]; then
    STATUS="degraded"
fi

# Output
if [[ "$JSON_OUTPUT" == "true" ]]; then
    echo "{"
    echo "  \"vmid\": \"$VMID\","
    echo "  \"service_type\": \"$SERVICE_TYPE\","
    echo "  \"status\": \"$STATUS\","
    echo "  \"container_running\": ${HEALTH[container_running]},"
    echo "  \"service_running\": ${HEALTH[service_running]},"
    echo "  \"besu_process\": ${HEALTH[besu_process]},"
    echo "  \"p2p_listening\": ${HEALTH[p2p_listening]},"
    echo "  \"rpc_available\": ${HEALTH[rpc_available]},"
    [[ -n "${HEALTH[block_height]}" ]] && echo "  \"block_height\": ${HEALTH[block_height]},"
    [[ -n "${HEALTH[chain_id]}" ]] && echo "  \"chain_id\": ${HEALTH[chain_id]},"
    [[ -n "${HEALTH[peer_count]}" ]] && echo "  \"peer_count\": ${HEALTH[peer_count]},"
    echo "  \"errors\": $(python3 -c "import json; print(json.dumps(${HEALTH[errors]}))" 2>/dev/null || echo "[]")"
    echo "}"
else
    log_info "========================================="
    log_info "Node Health Check: Container $VMID"
    log_info "========================================="
    log_info "Service Type: $SERVICE_TYPE"
    log_info "Status: $STATUS"
    log_info ""
    log_info "Container: $([ "${HEALTH[container_running]}" == "true" ] && log_success "Running" || log_error "Not running")"
    log_info "Service: $([ "${HEALTH[service_running]}" == "true" ] && log_success "Running" || log_error "Not running")"
    log_info "Besu Process: $([ "${HEALTH[besu_process]}" == "true" ] && log_success "Running" || log_error "Not running")"
    log_info "P2P Listening: $([ "${HEALTH[p2p_listening]}" == "true" ] && log_success "Yes (port 30303)" || log_error "No")"
    log_info "RPC Available: $([ "${HEALTH[rpc_available]}" == "true" ] && log_success "Yes (port 8545)" || log_info "No (RPC disabled)")"
    
    if [[ -n "${HEALTH[block_height]}" ]]; then
        log_info "Block Height: ${HEALTH[block_height]}"
    fi
    
    if [[ -n "${HEALTH[chain_id]}" ]]; then
        log_info "Chain ID: ${HEALTH[chain_id]}"
    fi
    
    if [[ -n "${HEALTH[peer_count]}" ]]; then
        log_info "Peer Count: ${HEALTH[peer_count]}"
    fi
    
    if [[ ${#HEALTH[errors]} -gt 0 ]]; then
        log_info ""
        log_error "Errors:"
        for error in "${HEALTH[errors][@]}"; do
            log_error "  - $error"
        done
    fi
fi

# Exit code based on status
if [[ "$STATUS" == "healthy" ]]; then
    exit 0
elif [[ "$STATUS" == "degraded" ]]; then
    exit 1
else
    exit 2
fi

