#!/usr/bin/env bash
# Fix All Infrastructure Issues
# Automates fixes for: DNS records, duplicate cleanup, tunnel configuration instructions
# 
# Usage: ./scripts/fix-all-infrastructure-issues.sh

set -euo pipefail

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

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

log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
log_error() { echo -e "${RED}[✗]${NC} $1"; }

# Tunnel ID from current configuration
TUNNEL_ID="10ab22da-8ea3-4e2e-a896-27ece2211a05"
TUNNEL_TARGET="${TUNNEL_ID}.cfargotunnel.com"
DOMAIN="d-bis.org"
CENTRAL_NGINX_IP="192.168.11.21"
CENTRAL_NGINX_PORT="80"

echo ""
log_info "═══════════════════════════════════════════════════════════"
log_info "  FIXING ALL INFRASTRUCTURE ISSUES"
log_info "═══════════════════════════════════════════════════════════"
echo ""

# Check for .env file
if [ ! -f "$ENV_FILE" ]; then
    log_error ".env file not found at: $ENV_FILE"
    log_info "Please create .env file with Cloudflare credentials:"
    log_info "  CLOUDFLARE_API_TOKEN=your-token"
    log_info "  OR"
    log_info "  CLOUDFLARE_API_KEY=your-key"
    log_info "  CLOUDFLARE_EMAIL=your-email"
    log_info ""
    log_info "See: scripts/get-cloudflare-api-key.md for instructions"
    exit 1
fi

# Source .env file
source "$ENV_FILE"

# Determine authentication method
AUTH_HEADERS=()
if [ -n "${CLOUDFLARE_API_TOKEN:-}" ]; then
    AUTH_HEADERS=(-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN")
    log_success "Using API Token authentication"
elif [ -n "${CLOUDFLARE_API_KEY:-}" ] && [ -n "${CLOUDFLARE_EMAIL:-}" ]; then
    AUTH_HEADERS=(-H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY")
    log_success "Using API Key authentication"
else
    log_error "No Cloudflare credentials found in .env"
    exit 1
fi

# Get Zone ID
log_info "Getting Cloudflare Zone ID for $DOMAIN..."
ZONE_RESPONSE=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \
    "${AUTH_HEADERS[@]}" \
    -H "Content-Type: application/json")

ZONE_ID=$(echo "$ZONE_RESPONSE" | jq -r '.result[0].id // empty' 2>/dev/null || echo "")

if [ -z "$ZONE_ID" ] || [ "$ZONE_ID" = "null" ]; then
    log_error "Failed to get zone ID for $DOMAIN"
    echo "$ZONE_RESPONSE" | jq '.' 2>/dev/null || echo "$ZONE_RESPONSE"
    exit 1
fi

log_success "Zone ID: $ZONE_ID"

# Cloudflare API function
cloudflare_api() {
    local method=$1
    local endpoint=$2
    local data=${3:-}
    
    if [ -n "$data" ]; then
        curl -s -X "$method" \
            "https://api.cloudflare.com/client/v4/$endpoint" \
            "${AUTH_HEADERS[@]}" \
            -H "Content-Type: application/json" \
            -d "$data"
    else
        curl -s -X "$method" \
            "https://api.cloudflare.com/client/v4/$endpoint" \
            "${AUTH_HEADERS[@]}" \
            -H "Content-Type: application/json"
    fi
}

# Check if DNS record exists
record_exists() {
    local record_type=$1
    local record_name=$2
    
    local response=$(cloudflare_api "GET" "zones/$ZONE_ID/dns_records?type=$record_type&name=$record_name")
    echo "$response" | jq -e '.result | length > 0' > /dev/null 2>&1
}

# Get DNS record ID
get_record_id() {
    local record_type=$1
    local record_name=$2
    
    local response=$(cloudflare_api "GET" "zones/$ZONE_ID/dns_records?type=$record_type&name=$record_name")
    echo "$response" | jq -r '.result[0].id // empty'
}

# Get all record IDs for a name (for duplicates)
get_all_record_ids() {
    local record_type=$1
    local record_name=$2
    
    local response=$(cloudflare_api "GET" "zones/$ZONE_ID/dns_records?type=$record_type&name=$record_name")
    echo "$response" | jq -r '.result[].id'
}

# Create or update DNS record
create_or_update_dns() {
    local record_type=$1
    local record_name=$2
    local record_content=$3
    local proxied=${4:-true}
    
    if record_exists "$record_type" "$record_name"; then
        log_info "Updating DNS record: $record_name ($record_type) → $record_content"
        local record_id=$(get_record_id "$record_type" "$record_name")
        
        local data=$(jq -n \
            --arg type "$record_type" \
            --arg name "$record_name" \
            --arg content "$record_content" \
            --argjson proxied "$proxied" \
            '{
                type: $type,
                name: $name,
                content: $content,
                ttl: 1,
                proxied: $proxied
            }')
        
        local response=$(cloudflare_api "PUT" "zones/$ZONE_ID/dns_records/$record_id" "$data")
        
        if echo "$response" | jq -e '.success' > /dev/null; then
            log_success "DNS record updated: $record_name"
        else
            log_error "Failed to update DNS record: $record_name"
            echo "$response" | jq -r '.errors[0].message' 2>/dev/null || echo "$response"
            return 1
        fi
    else
        log_info "Creating DNS record: $record_name ($record_type) → $record_content"
        
        local data=$(jq -n \
            --arg type "$record_type" \
            --arg name "$record_name" \
            --arg content "$record_content" \
            --argjson proxied "$proxied" \
            '{
                type: $type,
                name: $name,
                content: $content,
                ttl: 1,
                proxied: $proxied
            }')
        
        local response=$(cloudflare_api "POST" "zones/$ZONE_ID/dns_records" "$data")
        
        if echo "$response" | jq -e '.success' > /dev/null; then
            log_success "DNS record created: $record_name"
        else
            log_error "Failed to create DNS record: $record_name"
            echo "$response" | jq -r '.errors[0].message' 2>/dev/null || echo "$response"
            return 1
        fi
    fi
}

# Delete DNS record
delete_dns_record() {
    local record_id=$1
    local record_name=$2
    
    log_info "Deleting DNS record: $record_name (ID: $record_id)"
    local response=$(cloudflare_api "DELETE" "zones/$ZONE_ID/dns_records/$record_id")
    
    if echo "$response" | jq -e '.success' > /dev/null; then
        log_success "DNS record deleted: $record_name"
    else
        log_error "Failed to delete DNS record: $record_name"
        echo "$response" | jq -r '.errors[0].message' 2>/dev/null || echo "$response"
        return 1
    fi
}

# Remove duplicate A records (keep first, delete rest)
remove_duplicate_a_records() {
    local record_name=$1
    
    log_info "Checking for duplicate A records: $record_name"
    local record_ids=($(get_all_record_ids "A" "$record_name"))
    
    if [ ${#record_ids[@]} -gt 1 ]; then
        log_warn "Found ${#record_ids[@]} A records for $record_name"
        
        # Get all records to see which IP to keep
        local response=$(cloudflare_api "GET" "zones/$ZONE_ID/dns_records?type=A&name=$record_name")
        local records=$(echo "$response" | jq -r '.result[] | "\(.id)|\(.content)"')
        
        # Keep the first record, delete the rest
        local first=true
        while IFS='|' read -r record_id content; do
            if [ "$first" = true ]; then
                log_info "Keeping A record: $record_name → $content (ID: $record_id)"
                first=false
            else
                delete_dns_record "$record_id" "$record_name → $content"
            fi
        done <<< "$records"
    else
        log_success "No duplicates found for $record_name"
    fi
}

echo ""
log_info "═══════════════════════════════════════════════════════════"
log_info "  STEP 1: CREATE MISSING DNS CNAME RECORDS"
log_info "═══════════════════════════════════════════════════════════"
echo ""

# Missing DNS CNAME records to create
declare -a MISSING_DNS=(
    "rpc-http-pub.d-bis.org"
    "rpc-ws-pub.d-bis.org"
    "rpc-http-prv.d-bis.org"
    "rpc-ws-prv.d-bis.org"
    "dbis-admin.d-bis.org"
    "dbis-api.d-bis.org"
    "dbis-api-2.d-bis.org"
    "mim4u.org"
    "www.mim4u.org"
)

for domain in "${MISSING_DNS[@]}"; do
    create_or_update_dns "CNAME" "$domain" "$TUNNEL_TARGET" true
    sleep 0.5  # Rate limiting
done

echo ""
log_info "═══════════════════════════════════════════════════════════"
log_info "  STEP 2: REMOVE DUPLICATE DNS A RECORDS"
log_info "═══════════════════════════════════════════════════════════"
echo ""

# Domains with duplicate A records
declare -a DUPLICATE_DOMAINS=(
    "besu.d-bis.org"
    "blockscout.d-bis.org"
    "explorer.d-bis.org"
    "d-bis.org"
)

for domain in "${DUPLICATE_DOMAINS[@]}"; do
    remove_duplicate_a_records "$domain"
    sleep 0.5  # Rate limiting
done

echo ""
log_info "═══════════════════════════════════════════════════════════"
log_info "  STEP 3: TUNNEL CONFIGURATION INSTRUCTIONS"
log_info "═══════════════════════════════════════════════════════════"
echo ""

log_warn "Tunnel configuration must be done manually in Cloudflare dashboard"
log_info ""
log_info "Tunnel: rpc-http-pub.d-bis.org (ID: $TUNNEL_ID)"
log_info "Status: Currently DOWN - needs configuration"
log_info ""
log_info "Action Required:"
log_info "1. Go to: https://one.dash.cloudflare.com/"
log_info "2. Navigate to: Zero Trust → Networks → Tunnels"
log_info "3. Click on: rpc-http-pub.d-bis.org"
log_info "4. Click: Configure → Public Hostnames"
log_info "5. Update all HTTP endpoints to route to: http://${CENTRAL_NGINX_IP}:${CENTRAL_NGINX_PORT}"
log_info ""
log_info "HTTP Endpoints (route to central Nginx):"
for domain in "explorer.d-bis.org" "rpc-http-pub.d-bis.org" "rpc-http-prv.d-bis.org" \
              "dbis-admin.d-bis.org" "dbis-api.d-bis.org" "dbis-api-2.d-bis.org" \
              "mim4u.org" "www.mim4u.org"; do
    log_info "  - $domain → http://${CENTRAL_NGINX_IP}:${CENTRAL_NGINX_PORT}"
done
log_info ""
log_info "WebSocket Endpoints (keep direct routing):"
log_info "  - rpc-ws-pub.d-bis.org → https://192.168.11.252:443"
log_info "  - rpc-ws-prv.d-bis.org → https://192.168.11.251:443"
log_info ""

echo ""
log_info "═══════════════════════════════════════════════════════════"
log_info "  STEP 4: VERIFY NETWORK CONNECTIVITY"
log_info "═══════════════════════════════════════════════════════════"
echo ""

# Test connectivity
log_info "Testing network connectivity..."

# Test pve2 → ml110
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "ping -c 1 -W 2 192.168.11.10 >/dev/null 2>&1"; then
    log_success "Network: pve2 (192.168.11.12) → ml110 (192.168.11.10) ✓"
else
    log_error "Network: pve2 (192.168.11.12) → ml110 (192.168.11.10) ✗"
fi

# Test central Nginx → RPC nodes
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.250:443/health >/dev/null 2>&1 || pct exec 105 -- curl -s -m 2 -k https://192.168.11.250:443/health >/dev/null 2>&1"; then
    log_success "Network: Central Nginx → RPC-1 (192.168.11.250) ✓"
else
    log_warn "Network: Central Nginx → RPC-1 (192.168.11.250) - May need verification"
fi

if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 -k https://192.168.11.251:443/health >/dev/null 2>&1"; then
    log_success "Network: Central Nginx → RPC-2 (192.168.11.251) ✓"
else
    log_warn "Network: Central Nginx → RPC-2 (192.168.11.251) - May need verification"
fi

if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 -k https://192.168.11.252:443/health >/dev/null 2>&1"; then
    log_success "Network: Central Nginx → RPC-3 (192.168.11.252) ✓"
else
    log_warn "Network: Central Nginx → RPC-3 (192.168.11.252) - May need verification"
fi

# Test central Nginx → DBIS services
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.130:80 >/dev/null 2>&1"; then
    log_success "Network: Central Nginx → DBIS Frontend (192.168.11.130) ✓"
else
    log_warn "Network: Central Nginx → DBIS Frontend (192.168.11.130) - May need verification"
fi

if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.150:3000/health >/dev/null 2>&1"; then
    log_success "Network: Central Nginx → DBIS API (192.168.11.150) ✓"
else
    log_warn "Network: Central Nginx → DBIS API (192.168.11.150) - May need verification"
fi

# Test central Nginx → Blockscout
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.140:80/health >/dev/null 2>&1"; then
    log_success "Network: Central Nginx → Blockscout (192.168.11.140) ✓"
else
    log_warn "Network: Central Nginx → Blockscout (192.168.11.140) - May need verification"
fi

# Test central Nginx → MIM
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.19:80 >/dev/null 2>&1"; then
    log_success "Network: Central Nginx → MIM (192.168.11.19) ✓"
else
    log_warn "Network: Central Nginx → MIM (192.168.11.19) - May need verification"
fi

echo ""
log_info "═══════════════════════════════════════════════════════════"
log_info "  SUMMARY"
log_info "═══════════════════════════════════════════════════════════"
echo ""

log_success "DNS CNAME records created/updated: ${#MISSING_DNS[@]}"
log_success "Duplicate A records cleaned: ${#DUPLICATE_DOMAINS[@]}"
log_warn "Tunnel configuration: Manual action required (see instructions above)"
echo ""
log_info "Next Steps:"
log_info "1. ✅ DNS records updated"
log_info "2. ⏳ Update Cloudflare tunnel configuration (manual)"
log_info "3. ⏳ Wait 1-2 minutes for DNS propagation"
log_info "4. ⏳ Test all endpoints"
echo ""
log_info "Test commands:"
log_info "  curl https://rpc-http-pub.d-bis.org -X POST -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":1}'"
log_info "  curl https://explorer.d-bis.org/api/v2/stats"
log_info "  curl https://dbis-admin.d-bis.org"
log_info "  curl https://mim4u.org"
echo ""

