#!/usr/bin/env bash
# Prerequisites Check Script
# Validates that all required files and directories exist in the source project

set -euo pipefail

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

source "$PROJECT_ROOT/lib/common.sh" 2>/dev/null || {
    log_info() { echo "[INFO] $1"; }
    log_success() { echo "[✓] $1"; }
    log_warn() { echo "[WARNING] $1"; }
    log_error() { echo "[ERROR] $1"; }
}

# Source project path
SOURCE_PROJECT="${1:-}"
if [[ -z "$SOURCE_PROJECT" ]]; then
    SOURCE_PROJECT="${SOURCE_PROJECT:-/home/intlc/projects/smom-dbis-138}"
    log_info "Using default source project: $SOURCE_PROJECT"
fi

# Convert to absolute path
if [[ "$SOURCE_PROJECT" != /* ]]; then
    SOURCE_PROJECT="$(cd "$PROJECT_ROOT" && cd "$SOURCE_PROJECT" && pwd 2>/dev/null || echo "$PROJECT_ROOT/$SOURCE_PROJECT")"
fi

log_info "========================================="
log_info "Prerequisites Check"
log_info "========================================="
log_info ""
log_info "Source project: $SOURCE_PROJECT"
log_info ""

ERRORS=0
WARNINGS=0

# Check source project exists
if [[ ! -d "$SOURCE_PROJECT" ]]; then
    log_error "Source project directory not found: $SOURCE_PROJECT"
    exit 1
fi

log_success "Source project directory exists"

# Check for required top-level directories
log_info ""
log_info "=== Checking Required Directories ==="

REQUIRED_DIRS=(
    "config"
    "keys/validators"
)

for dir in "${REQUIRED_DIRS[@]}"; do
    if [[ -d "$SOURCE_PROJECT/$dir" ]]; then
        log_success "✓ $dir/ exists"
    else
        log_error "✗ $dir/ missing"
        ERRORS=$((ERRORS + 1))
    fi
done

# Check for config/nodes/ structure (node-specific directories)
HAS_NODE_DIRS=false
if [[ -d "$SOURCE_PROJECT/config/nodes" ]]; then
    log_success "✓ config/nodes/ directory exists"
    HAS_NODE_DIRS=true
    
    # Check for node subdirectories
    log_info ""
    log_info "Checking node-specific directories in config/nodes/:"
    NODE_DIRS=$(find "$SOURCE_PROJECT/config/nodes" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)
    if [[ $NODE_DIRS -gt 0 ]]; then
        log_success "✓ Found $NODE_DIRS node directory(ies)"
        log_info "  Sample node directories:"
        find "$SOURCE_PROJECT/config/nodes" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | head -5 | while read dir; do
            log_info "    - $(basename "$dir")"
        done
    else
        log_warn "⚠ config/nodes/ exists but is empty"
        WARNINGS=$((WARNINGS + 1))
    fi
else
    log_info "config/nodes/ not found (using flat config structure)"
fi

# Check for required files (flat structure)
log_info ""
log_info "=== Checking Required Files ==="

REQUIRED_FILES=(
    "config/genesis.json"
    "config/permissions-nodes.toml"
    "config/permissions-accounts.toml"
)

OPTIONAL_FILES=(
    "config/static-nodes.json"
    "config/config-validator.toml"
    "config/config-sentry.toml"
    "config/config-rpc-public.toml"
    "config/config-rpc-core.toml"
)

for file in "${REQUIRED_FILES[@]}"; do
    if [[ -f "$SOURCE_PROJECT/$file" ]]; then
        log_success "✓ $file exists"
    else
        log_error "✗ $file missing (REQUIRED)"
        ERRORS=$((ERRORS + 1))
    fi
done

for file in "${OPTIONAL_FILES[@]}"; do
    if [[ -f "$SOURCE_PROJECT/$file" ]]; then
        log_success "✓ $file exists"
    else
        log_warn "⚠ $file not found (optional, may be in config/nodes/)"
        WARNINGS=$((WARNINGS + 1))
    fi
done

# Check node-specific files if config/nodes/ exists
if [[ "$HAS_NODE_DIRS" == "true" ]]; then
    log_info ""
    log_info "=== Checking Node-Specific Files ==="
    
    # Check first node directory for expected files
    FIRST_NODE_DIR=$(find "$SOURCE_PROJECT/config/nodes" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | head -1)
    if [[ -n "$FIRST_NODE_DIR" ]] && [[ -d "$FIRST_NODE_DIR" ]]; then
        NODE_NAME=$(basename "$FIRST_NODE_DIR")
        log_info "Checking structure in: config/nodes/$NODE_NAME/"
        
        NODE_FILES=(
            "config.toml"
            "nodekey"
            "nodekey.pub"
        )
        
        for file in "${NODE_FILES[@]}"; do
            if [[ -f "$FIRST_NODE_DIR/$file" ]]; then
                log_success "✓ config/nodes/$NODE_NAME/$file exists"
            else
                log_warn "⚠ config/nodes/$NODE_NAME/$file not found"
                WARNINGS=$((WARNINGS + 1))
            fi
        done
        
        # List all files in the node directory
        log_info ""
        log_info "Files in config/nodes/$NODE_NAME/:"
        find "$FIRST_NODE_DIR" -type f -maxdepth 1 2>/dev/null | while read file; do
            log_info "  - $(basename "$file")"
        done
    fi
fi

# Check validator keys
log_info ""
log_info "=== Checking Validator Keys ==="

KEYS_DIR="$SOURCE_PROJECT/keys/validators"
if [[ -d "$KEYS_DIR" ]]; then
    KEY_COUNT=$(find "$KEYS_DIR" -mindepth 1 -maxdepth 1 -type d -name "validator-*" 2>/dev/null | wc -l)
    if [[ $KEY_COUNT -gt 0 ]]; then
        log_success "✓ Found $KEY_COUNT validator key directory(ies)"
        log_info "  Validator directories:"
        find "$KEYS_DIR" -mindepth 1 -maxdepth 1 -type d -name "validator-*" 2>/dev/null | while read dir; do
            log_info "    - $(basename "$dir")"
        done
        
        # Try to get expected count from config files, or use default
        EXPECTED_VALIDATORS=5
        # Try multiple possible config file locations
        CONFIG_PATHS=(
            "$SCRIPT_DIR/../../smom-dbis-138-proxmox/config/proxmox.conf"  # scripts/validation -> smom-dbis-138-proxmox/config
            "$SCRIPT_DIR/../../config/proxmox.conf"  # smom-dbis-138-proxmox/scripts/validation -> smom-dbis-138-proxmox/config
            "$SCRIPT_DIR/../../../smom-dbis-138-proxmox/config/proxmox.conf"  # scripts/validation -> smom-dbis-138-proxmox/config
            "$PROJECT_ROOT/smom-dbis-138-proxmox/config/proxmox.conf"
            "$PROJECT_ROOT/config/proxmox.conf"
            "$(dirname "$SOURCE_PROJECT")/../proxmox/smom-dbis-138-proxmox/config/proxmox.conf"
            "/home/intlc/projects/proxmox/smom-dbis-138-proxmox/config/proxmox.conf"
        )
        
        for CONFIG_FILE in "${CONFIG_PATHS[@]}"; do
            # Resolve relative paths
            if [[ "$CONFIG_FILE" != /* ]]; then
                CONFIG_FILE="$(cd "$SCRIPT_DIR" && cd "$(dirname "$CONFIG_FILE")" 2>/dev/null && pwd)/$(basename "$CONFIG_FILE")" 2>/dev/null || echo "$CONFIG_FILE"
            fi
            if [[ -f "$CONFIG_FILE" ]]; then
                # Extract VALIDATOR_COUNT value, handling comments on same line
                CONFIG_VALIDATOR_COUNT=$(grep "^VALIDATOR_COUNT=" "$CONFIG_FILE" 2>/dev/null | head -1 | sed 's/^VALIDATOR_COUNT=//' | sed 's/[[:space:]]*#.*$//' | tr -d ' "' || echo "")
                if [[ -n "$CONFIG_VALIDATOR_COUNT" ]] && [[ "$CONFIG_VALIDATOR_COUNT" =~ ^[0-9]+$ ]]; then
                    EXPECTED_VALIDATORS="$CONFIG_VALIDATOR_COUNT"
                    log_info "  Using VALIDATOR_COUNT=$EXPECTED_VALIDATORS from $(basename "$(dirname "$CONFIG_FILE")")/$(basename "$CONFIG_FILE")"
                    break
                fi
            fi
        done
        
        if [[ $KEY_COUNT -eq $EXPECTED_VALIDATORS ]]; then
            log_success "✓ Validator key count matches expected: $EXPECTED_VALIDATORS"
        else
            log_warn "⚠ Validator key count mismatch: expected $EXPECTED_VALIDATORS, found $KEY_COUNT"
            log_info "  Note: This may be acceptable if you're deploying fewer validators than configured"
            log_info "  Update VALIDATOR_COUNT=$KEY_COUNT in config/proxmox.conf if this is intentional"
            WARNINGS=$((WARNINGS + 1))
        fi
    else
        log_warn "⚠ keys/validators/ exists but no validator-* directories found"
        WARNINGS=$((WARNINGS + 1))
    fi
else
    log_error "✗ keys/validators/ directory missing"
    ERRORS=$((ERRORS + 1))
fi

# Validate genesis.json structure
log_info ""
log_info "=== Validating Genesis.json ==="
GENESIS_FILE="$SOURCE_PROJECT/config/genesis.json"
if [[ -f "$GENESIS_FILE" ]]; then
    # Check JSON syntax
    if python3 -m json.tool "$GENESIS_FILE" >/dev/null 2>&1; then
        log_success "✓ genesis.json syntax valid"
        
        # Check for QBFT configuration
        if python3 -c "import sys, json; data=json.load(open('$GENESIS_FILE')); exit(0 if 'config' in data and 'qbft' in data.get('config', {}) else 1)" 2>/dev/null; then
            log_success "✓ QBFT configuration present in genesis.json"
        else
            log_error "✗ QBFT configuration missing in genesis.json"
            ERRORS=$((ERRORS + 1))
        fi
        
        # Check for extraData field
        if python3 -c "import sys, json; data=json.load(open('$GENESIS_FILE')); exit(0 if 'extraData' in data else 1)" 2>/dev/null; then
            log_success "✓ extraData field present in genesis.json"
            
            # Validate extraData format
            EXTRA_DATA=$(python3 -c "import sys, json; print(json.load(open('$GENESIS_FILE')).get('extraData', ''))" 2>/dev/null)
            if [[ "$EXTRA_DATA" =~ ^0x[0-9a-fA-F]*$ ]] || [[ -z "$EXTRA_DATA" ]]; then
                log_success "✓ extraData format valid"
            else
                log_error "✗ extraData format invalid: $EXTRA_DATA"
                ERRORS=$((ERRORS + 1))
            fi
        else
            log_error "✗ extraData field missing in genesis.json"
            ERRORS=$((ERRORS + 1))
        fi
        
        # For dynamic validators, verify no validators array in QBFT
        if python3 -c "import sys, json; data=json.load(open('$GENESIS_FILE')); qbft=data.get('config', {}).get('qbft', {}); exit(0 if 'validators' not in qbft else 1)" 2>/dev/null; then
            log_success "✓ Dynamic validator setup confirmed (no validators array in QBFT)"
        else
            log_warn "⚠ Validators array found in QBFT config (expected for dynamic validators)"
            WARNINGS=$((WARNINGS + 1))
        fi
    else
        log_error "✗ genesis.json syntax invalid"
        ERRORS=$((ERRORS + 1))
    fi
else
    log_error "✗ genesis.json not found"
    ERRORS=$((ERRORS + 1))
fi

# Summary
log_info ""
log_info "========================================="
log_info "Prerequisites Check Summary"
log_info "========================================="
log_info "Errors: $ERRORS"
log_info "Warnings: $WARNINGS"
log_info ""

if [[ $ERRORS -eq 0 ]]; then
    if [[ $WARNINGS -eq 0 ]]; then
    log_success "✓ All prerequisites met!"
    log_info ""
    log_info "Recommended next steps:"
    log_info "  1. Verify storage configuration: sudo ./scripts/validation/verify-storage-config.sh"
    log_info "  2. Verify network configuration: ./scripts/validation/verify-network-config.sh"
    log_info "  3. Pre-cache OS template: sudo ./scripts/deployment/pre-cache-os-template.sh"
    log_info ""
    log_info "Or run all verifications: ./scripts/validation/verify-all.sh $SOURCE_PROJECT"
    exit 0
    else
    log_warn "⚠ Prerequisites met with $WARNINGS warning(s)"
    log_info "Review warnings above, but deployment may proceed"
    log_info ""
    log_info "Recommended next steps:"
    log_info "  1. Review warnings above"
    log_info "  2. Verify storage configuration: sudo ./scripts/validation/verify-storage-config.sh"
    log_info "  3. Verify network configuration: ./scripts/validation/verify-network-config.sh"
    exit 0
    fi
else
    log_error "✗ Prerequisites check failed with $ERRORS error(s)"
    log_info "Please fix the errors before proceeding with deployment"
    exit 1
fi


# Check for CCIP configuration files (if CCIP deployment planned)
log_info ""
log_info "=== Checking CCIP Configuration Files ==="

CCIP_REQUIRED_FILES=(
    "config/ccip/ops-config.yaml"
    "config/ccip/commit-config.yaml"
    "config/ccip/exec-config.yaml"
    "config/ccip/rmn-config.yaml"
)

CCIP_OPTIONAL_FILES=(
    "config/ccip/monitor-config.yaml"
    "config/ccip/secrets.yaml"
)

CCIP_FILES_EXIST=false
if [[ -d "$SOURCE_PROJECT/config/ccip" ]] || [[ -d "$SOURCE_PROJECT/ccip" ]]; then
    CCIP_FILES_EXIST=true
    log_info "CCIP configuration directory found"
    
    for file in "${CCIP_REQUIRED_FILES[@]}"; do
        if [[ -f "$SOURCE_PROJECT/$file" ]]; then
            log_success "✓ $file exists"
        else
            # Try alternative location
            alt_file="${file/config\/ccip/ccip}"
            if [[ -f "$SOURCE_PROJECT/$alt_file" ]]; then
                log_success "✓ $alt_file exists (alternative location)"
            else
                log_warn "⚠ $file not found (may be optional or in different location)"
                WARNINGS=$((WARNINGS + 1))
            fi
        fi
    done
    
    for file in "${CCIP_OPTIONAL_FILES[@]}"; do
        if [[ -f "$SOURCE_PROJECT/$file" ]]; then
            log_success "✓ $file exists"
        else
            log_info "  (optional) $file not found"
        fi
    done
else
    log_info "CCIP configuration directory not found (CCIP deployment may not be planned)"
fi

# Check for other service configurations
log_info ""
log_info "=== Checking Other Service Configuration Files ==="

SERVICE_CONFIGS=(
    "config/blockscout.env"
    "config/firefly/config.yaml"
    "config/fabric/network-config.yaml"
    "config/indy/pool-config.yaml"
    "config/cacti/config.yaml"
)

for config in "${SERVICE_CONFIGS[@]}"; do
    service_name=$(basename "$(dirname "$config")")
    if [[ -f "$SOURCE_PROJECT/$config" ]]; then
        log_success "✓ $config exists"
    else
        log_info "  (optional) $config not found - $service_name may use different config location"
    fi
done

