#!/bin/bash
# Info: Prepare script for Polkadot Validator
# Author: Provisioning System
# Release: 1.0
# Date: 2025-07-24

USAGE="prepare-polkadot-validator.sh"
[ "$1" == "-h" ] && echo "$USAGE" && exit 1

[ -r "env-polkadot-validator" ] && . ./env-polkadot-validator

echo "Preparing Polkadot Validator environment..."

# Check if running as root for system preparation
if [ "$EUID" -ne 0 ]; then
    echo "This preparation script must be run as root"
    exit 1
fi

# Validate system requirements
echo "Validating system requirements..."

# Check CPU cores
CPU_CORES=$(nproc)
if [ "$CPU_CORES" -lt 8 ]; then
    echo "❌ CRITICAL: Polkadot validators require at least 8 CPU cores. Found: $CPU_CORES"
    exit 1
else
    echo "✅ CPU cores: $CPU_CORES (minimum 8 required)"
fi

# Check memory
TOTAL_MEM=$(free -g | awk '/^Mem:/{print $2}')
if [ "$TOTAL_MEM" -lt 32 ]; then
    echo "❌ CRITICAL: Polkadot validators require at least 32GB RAM. Found: ${TOTAL_MEM}GB"
    exit 1
else
    echo "✅ Memory: ${TOTAL_MEM}GB (minimum 32GB required)"
fi

# Check storage
STORAGE_PATH=${POLKADOT_BASE_PATH:-/var/lib/polkadot/data}
PARENT_DIR=$(dirname "$STORAGE_PATH")
[ ! -d "$PARENT_DIR" ] && PARENT_DIR="/"

AVAILABLE_SPACE_KB=$(df "$PARENT_DIR" | awk 'NR==2 {print $4}')
AVAILABLE_SPACE_GB=$((AVAILABLE_SPACE_KB / 1024 / 1024))

if [ "$AVAILABLE_SPACE_GB" -lt 2000 ]; then
    echo "❌ CRITICAL: Polkadot validators require at least 2TB NVMe SSD storage"
    echo "Available: ${AVAILABLE_SPACE_GB}GB"
    exit 1
else
    echo "✅ Storage: ${AVAILABLE_SPACE_GB}GB available (minimum 2TB required)"
fi

# Check if storage is SSD (best effort)
STORAGE_DEVICE=$(df "$PARENT_DIR" | awk 'NR==2 {print $1}' | sed 's/[0-9]*$//')
if [ -f "/sys/block/$(basename "$STORAGE_DEVICE")/queue/rotational" ]; then
    IS_ROTATIONAL=$(cat "/sys/block/$(basename "$STORAGE_DEVICE")/queue/rotational" 2>/dev/null || echo "1")
    if [ "$IS_ROTATIONAL" = "0" ]; then
        echo "✅ Storage type: SSD/NVMe detected"
    else
        echo "⚠️  WARNING: Rotational storage detected. NVMe SSD strongly recommended for validators"
    fi
fi

# Check network connectivity
echo "Checking network connectivity..."

# Test internet connectivity
if ping -c 1 -W 5 8.8.8.8 >/dev/null 2>&1; then
    echo "✅ Internet connectivity: Available"
else
    echo "❌ CRITICAL: No internet connectivity detected"
    exit 1
fi

# Check DNS resolution
if nslookup github.com >/dev/null 2>&1; then
    echo "✅ DNS resolution: Working"
else
    echo "❌ CRITICAL: DNS resolution not working"
    exit 1
fi

# Test GitHub access (for binary downloads)
if curl -s --connect-timeout 10 https://api.github.com/repos/paritytech/polkadot/releases/latest >/dev/null; then
    echo "✅ GitHub API access: Available"
else
    echo "❌ CRITICAL: Cannot access GitHub API for Polkadot releases"
    exit 1
fi

# Validate required ports
echo "Checking port availability..."

REQUIRED_PORTS="30333 9933 9944 9615"
for port in $REQUIRED_PORTS; do
    if ss -tulnp | grep -q ":${port} "; then
        echo "⚠️  WARNING: Port $port is already in use"
        ss -tulnp | grep ":${port} "
    else
        echo "✅ Port $port: Available"
    fi
done

# Check system limits
echo "Checking system limits..."

# File descriptor limits
CURRENT_ULIMIT=$(ulimit -n)
if [ "$CURRENT_ULIMIT" -lt 65536 ]; then
    echo "⚠️  WARNING: File descriptor limit is $CURRENT_ULIMIT, should be at least 65536"
    echo "Consider adding to /etc/security/limits.conf:"
    echo "* soft nofile 65536"
    echo "* hard nofile 65536"
else
    echo "✅ File descriptor limit: $CURRENT_ULIMIT"
fi

# Check systemd
if ! systemctl --version >/dev/null 2>&1; then
    echo "❌ CRITICAL: systemd not available"
    exit 1
else
    echo "✅ Systemd: Available"
fi

# Validate environment variables
echo "Validating environment configuration..."

REQUIRED_VARS="POLKADOT_VERSION POLKADOT_CHAIN POLKADOT_VALIDATOR_NAME"
for var in $REQUIRED_VARS; do
    if [ -z "${!var}" ]; then
        echo "❌ CRITICAL: Required environment variable $var is not set"
        exit 1
    else
        echo "✅ $var: ${!var}"
    fi
done

# Validate chain name
VALID_CHAINS="polkadot kusama westend"
CHAIN_VALID=false
for chain in $VALID_CHAINS; do
    if [ "${POLKADOT_CHAIN}" = "$chain" ]; then
        CHAIN_VALID=true
        break
    fi
done

if [ "$CHAIN_VALID" = "false" ]; then
    echo "❌ CRITICAL: Invalid chain '${POLKADOT_CHAIN}'. Valid chains: $VALID_CHAINS"
    exit 1
fi

# Check for existing installation
echo "Checking for existing Polkadot installation..."

POLKADOT_BIN=${POLKADOT_BIN_PATH:-/usr/local/bin/polkadot}
if [ -f "$POLKADOT_BIN" ]; then
    VERSION_OUTPUT=$("$POLKADOT_BIN" --version 2>/dev/null || echo "unknown")
    echo "⚠️  WARNING: Existing Polkadot installation found: $VERSION_OUTPUT"
    echo "Installation will overwrite existing binary"
fi

# Check systemd service
if systemctl list-unit-files | grep -q "polkadot-validator.service"; then
    echo "⚠️  WARNING: polkadot-validator.service already exists"
    SERVICE_STATUS=$(systemctl is-active polkadot-validator.service 2>/dev/null || echo "inactive")
    echo "Current status: $SERVICE_STATUS"
fi

# Validate user configuration
POLKADOT_USER=${POLKADOT_RUN_USER:-polkadot}
if id "$POLKADOT_USER" >/dev/null 2>&1; then
    echo "⚠️  WARNING: User $POLKADOT_USER already exists"
    USER_HOME=$(getent passwd "$POLKADOT_USER" | cut -d: -f6)
    echo "User home: $USER_HOME"
else
    echo "✅ User $POLKADOT_USER: Will be created"
fi

# Check directory permissions
echo "Checking directory structure..."

DIRECTORIES="/etc/polkadot /var/lib/polkadot /var/log/polkadot /var/backups/polkadot"
for dir in $DIRECTORIES; do
    if [ -d "$dir" ]; then
        OWNER=$(stat -c '%U:%G' "$dir" 2>/dev/null || echo "unknown")
        PERMS=$(stat -c '%a' "$dir" 2>/dev/null || echo "unknown")
        echo "⚠️  WARNING: Directory $dir already exists (owner: $OWNER, perms: $PERMS)"
    else
        echo "✅ Directory $dir: Will be created"
    fi
done

# Security checks
echo "Performing security checks..."

# Check if fail2ban is available
if command -v fail2ban-client >/dev/null 2>&1; then
    echo "✅ fail2ban: Available"
else
    echo "⚠️  WARNING: fail2ban not installed (will be installed during setup)"
fi

# Check firewall
if command -v ufw >/dev/null 2>&1; then
    UFW_STATUS=$(ufw status | head -1)
    echo "✅ UFW firewall: $UFW_STATUS"
elif command -v firewall-cmd >/dev/null 2>&1; then
    FIREWALLD_STATUS=$(systemctl is-active firewalld 2>/dev/null || echo "inactive")
    echo "✅ firewalld: $FIREWALLD_STATUS"
else
    echo "⚠️  WARNING: No firewall detected (will be configured during setup)"
fi

# Check for automatic updates
if command -v unattended-upgrades >/dev/null 2>&1; then
    echo "✅ Automatic updates: unattended-upgrades available"
elif command -v dnf >/dev/null 2>&1; then
    echo "✅ Automatic updates: dnf-automatic available"
else
    echo "⚠️  WARNING: Automatic update system not detected"
fi

# Time synchronization check
if systemctl is-active --quiet systemd-timesyncd || systemctl is-active --quiet ntp || systemctl is-active --quiet chrony; then
    echo "✅ Time synchronization: Active"
else
    echo "⚠️  WARNING: Time synchronization service not active"
    echo "Accurate time is critical for validators"
fi

# Check entropy
ENTROPY=$(cat /proc/sys/kernel/random/entropy_avail 2>/dev/null || echo "unknown")
if [ "$ENTROPY" != "unknown" ] && [ "$ENTROPY" -lt 1000 ]; then
    echo "⚠️  WARNING: Low entropy ($ENTROPY). Consider installing haveged or rng-tools"
else
    echo "✅ System entropy: $ENTROPY"
fi

# Final validation summary
echo ""
echo "========================================="
echo "Polkadot Validator Preparation Summary"
echo "========================================="
echo "Chain: ${POLKADOT_CHAIN}"
echo "Validator name: ${POLKADOT_VALIDATOR_NAME}"
echo "Version: ${POLKADOT_VERSION}"
echo "User: ${POLKADOT_USER}"
echo ""

# Check for critical issues
CRITICAL_ISSUES=0

# Re-check critical requirements
if [ "$CPU_CORES" -lt 8 ]; then
    echo "❌ CRITICAL: Insufficient CPU cores"
    CRITICAL_ISSUES=$((CRITICAL_ISSUES + 1))
fi

if [ "$TOTAL_MEM" -lt 32 ]; then
    echo "❌ CRITICAL: Insufficient memory"
    CRITICAL_ISSUES=$((CRITICAL_ISSUES + 1))
fi

if [ "$AVAILABLE_SPACE_GB" -lt 2000 ]; then
    echo "❌ CRITICAL: Insufficient storage"
    CRITICAL_ISSUES=$((CRITICAL_ISSUES + 1))
fi

if [ "$CRITICAL_ISSUES" -gt 0 ]; then
    echo ""
    echo "❌ PREPARATION FAILED: $CRITICAL_ISSUES critical issue(s) found"
    echo "Please resolve the above issues before proceeding with installation"
    exit 1
fi

echo "✅ All critical requirements met"
echo ""
echo "NEXT STEPS:"
echo "1. Review any warnings above"
echo "2. Run the installation script: ./install-polkadot-validator.sh"
echo "3. Configure session keys after node sync"
echo "4. Set up staking and validation"
echo ""
echo "SECURITY REMINDERS:"
echo "- Ensure this server has proper backup procedures"
echo "- Monitor the validator continuously"
echo "- Keep the system updated"
echo "- Never run duplicate validators with the same keys"
echo ""

exit 0