#!/bin/bash
# Complete Cloudflare Configuration for Explorer - Automated
# Uses .env credentials to configure DNS, SSL, and tunnel routes

set -euo pipefail

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
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"; }
log_section() { echo -e "${CYAN}════════════════════════════════════════${NC}"; }

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

# Configuration
DOMAIN="${DOMAIN:-d-bis.org}"
EXPLORER_DOMAIN="explorer.d-bis.org"
EXPLORER_IP="${EXPLORER_IP:-192.168.11.140}"
EXPLORER_PORT="${EXPLORER_PORT:-80}"
VMID=5000
PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}"
TUNNEL_TOKEN="eyJhIjoiNTJhZDU3YTcxNjcxYzVmYzAwOWVkZjA3NDQ2NTgxOTYiLCJ0IjoiYjAyZmUxZmUtY2I3ZC00ODRlLTkwOWItN2NjNDEyOThlYmU4IiwicyI6Ik5HTmtOV0kwWXpNdFpUVmxaUzAwTVRFMkxXRXdNMk10WlRJNU1ETTFaRFF4TURBMiJ9"

echo ""
log_section
log_info "  COMPLETE CLOUDFLARE EXPLORER CONFIGURATION"
log_info "  Using .env Credentials for Full Automation"
log_section
echo ""

# Step 1: Load .env file
log_info "Step 1: Loading credentials from .env file..."
if [ ! -f "$ENV_FILE" ]; then
    log_error ".env file not found: $ENV_FILE"
    log_info "Looking for .env files..."
    find "$SCRIPT_DIR/.." -maxdepth 2 -name ".env" -type f 2>/dev/null | head -3
    log_info ""
    log_info "Please create .env file with:"
    echo "  CLOUDFLARE_API_TOKEN=your-token"
    echo "  CLOUDFLARE_ZONE_ID=your-zone-id (optional)"
    echo "  CLOUDFLARE_ACCOUNT_ID=your-account-id (optional)"
    echo "  DOMAIN=d-bis.org"
    exit 1
fi

# Source .env file
set -a
source "$ENV_FILE"
set +a

log_success ".env file loaded"

# Check for required credentials
CLOUDFLARE_API_TOKEN="${CLOUDFLARE_API_TOKEN:-}"
CLOUDFLARE_API_KEY="${CLOUDFLARE_API_KEY:-}"
CLOUDFLARE_EMAIL="${CLOUDFLARE_EMAIL:-}"
CLOUDFLARE_ZONE_ID="${CLOUDFLARE_ZONE_ID:-}"
CLOUDFLARE_ACCOUNT_ID="${CLOUDFLARE_ACCOUNT_ID:-}"

# Determine auth method
AUTH_METHOD=""
AUTH_HEADERS=()

# Check for API_TOKEN first (preferred), then API_KEY
if [ -n "$CLOUDFLARE_API_TOKEN" ]; then
    AUTH_METHOD="token"
    AUTH_HEADERS=(-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN")
    log_success "Using API Token authentication"
elif [ -n "$CLOUDFLARE_API_KEY" ] && [ -n "$CLOUDFLARE_EMAIL" ]; then
    AUTH_METHOD="key"
    # Remove quotes from API_KEY if present
    CLOUDFLARE_API_KEY=$(echo "$CLOUDFLARE_API_KEY" | tr -d '"')
    CLOUDFLARE_EMAIL=$(echo "$CLOUDFLARE_EMAIL" | tr -d '"')
    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 API credentials found in .env"
    log_info "Required: CLOUDFLARE_API_TOKEN or (CLOUDFLARE_API_KEY + CLOUDFLARE_EMAIL)"
    exit 1
fi

# Function to find container node
find_container_node() {
    ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" \
        "for node in ml110 pve pve2; do if pvesh get /nodes/\$node/lxc/$VMID/status/current --output-format json >/dev/null 2>&1; then echo \$node; break; fi; done" 2>/dev/null || echo "pve2"
}

# Function to execute command in container
exec_container() {
    local cmd="$1"
    # Try direct pct exec via main host first
    ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct exec $VMID -- bash -c '$cmd'" 2>&1
}

# Step 2: Install Cloudflare Tunnel Service
log_section
log_info "Step 2: Installing Cloudflare Tunnel Service"
log_section

log_info "Checking cloudflared installation..."
if ! exec_container "command -v cloudflared >/dev/null 2>&1"; then
    log_info "Installing cloudflared..."
    exec_container "cd /tmp && wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && dpkg -i cloudflared-linux-amd64.deb || apt install -f -y"
    log_success "cloudflared installed"
else
    log_success "cloudflared already installed"
fi

log_info "Installing tunnel service with token..."
INSTALL_OUTPUT=$(exec_container "cloudflared service install $TUNNEL_TOKEN 2>&1" || echo "INSTALL_FAILED")
if echo "$INSTALL_OUTPUT" | grep -q -E "successfully|installed|Service installed"; then
    log_success "Tunnel service installed"
else
    log_warn "Installation output: $INSTALL_OUTPUT"
    # Continue - service might already be installed
fi

log_info "Starting cloudflared service..."
exec_container "systemctl start cloudflared" || true
exec_container "systemctl enable cloudflared" || true
sleep 3

CLOUDFLARED_STATUS=$(exec_container "systemctl is-active cloudflared 2>/dev/null || echo 'inactive'")
if [ "$CLOUDFLARED_STATUS" = "active" ]; then
    log_success "Cloudflared service is running"
else
    log_warn "Cloudflared service is $CLOUDFLARED_STATUS"
fi

# Get tunnel ID
log_info "Getting tunnel ID..."
TUNNEL_LIST=$(exec_container "cloudflared tunnel list 2>&1" || echo "")
TUNNEL_ID=$(echo "$TUNNEL_LIST" | grep -v "NAME" | head -1 | awk '{print $1}' || echo "")

if [ -n "$TUNNEL_ID" ]; then
    log_success "Tunnel ID: $TUNNEL_ID"
else
    log_warn "Could not get tunnel ID from tunnel list"
    # Try to extract from token (base64 decode)
    TUNNEL_ID=$(echo "$TUNNEL_TOKEN" | base64 -d 2>/dev/null | jq -r '.TunnelID // empty' 2>/dev/null || echo "")
    if [ -n "$TUNNEL_ID" ]; then
        log_success "Tunnel ID from token: $TUNNEL_ID"
    else
        log_error "Cannot determine tunnel ID"
        exit 1
    fi
fi

# Step 3: Get Zone ID
log_section
log_info "Step 3: Getting Cloudflare Zone ID"
log_section

if [ -z "$CLOUDFLARE_ZONE_ID" ]; then
    log_info "Fetching 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
        ERROR=$(echo "$ZONE_RESPONSE" | jq -r '.errors[0].message // "Unknown error"' 2>/dev/null || echo "API call failed")
        log_error "Failed to get zone ID: $ERROR"
        exit 1
    fi
    
    log_success "Zone ID: $ZONE_ID"
else
    ZONE_ID="$CLOUDFLARE_ZONE_ID"
    log_success "Using provided Zone ID: $ZONE_ID"
fi

# Step 4: Get Account ID (for tunnel configuration)
log_section
log_info "Step 4: Getting Cloudflare Account ID"
log_section

if [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then
    log_info "Fetching account ID..."
    ACCOUNT_RESPONSE=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts" \
        "${AUTH_HEADERS[@]}" \
        -H "Content-Type: application/json")
    
    CLOUDFLARE_ACCOUNT_ID=$(echo "$ACCOUNT_RESPONSE" | jq -r '.result[0].id // empty' 2>/dev/null || echo "")
    
    if [ -z "$CLOUDFLARE_ACCOUNT_ID" ] || [ "$CLOUDFLARE_ACCOUNT_ID" = "null" ]; then
        log_warn "Could not get account ID automatically"
    else
        log_success "Account ID: $CLOUDFLARE_ACCOUNT_ID"
    fi
else
    log_success "Using provided Account ID: $CLOUDFLARE_ACCOUNT_ID"
fi

# Step 5: Configure DNS Record
log_section
log_info "Step 5: Configuring DNS Record"
log_section

TARGET="${TUNNEL_ID}.cfargotunnel.com"
log_info "DNS Target: $TARGET"

# Check if record exists
EXISTING_RECORD=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=$EXPLORER_DOMAIN" \
    "${AUTH_HEADERS[@]}" \
    -H "Content-Type: application/json")

RECORD_ID=$(echo "$EXISTING_RECORD" | jq -r '.result[0].id // empty' 2>/dev/null || echo "")
EXISTING_TYPE=$(echo "$EXISTING_RECORD" | jq -r '.result[0].type // empty' 2>/dev/null || echo "")

DNS_DATA=$(jq -n \
    --arg name "explorer" \
    --arg target "$TARGET" \
    '{
        type: "CNAME",
        name: $name,
        content: $target,
        proxied: true,
        ttl: 1
    }')

if [ -n "$RECORD_ID" ] && [ "$RECORD_ID" != "null" ]; then
    log_info "Updating existing DNS record (ID: $RECORD_ID, Type: $EXISTING_TYPE)..."
    
    if [ "$EXISTING_TYPE" != "CNAME" ]; then
        log_warn "Existing record is type $EXISTING_TYPE, deleting and creating CNAME..."
        curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
            "${AUTH_HEADERS[@]}" \
            -H "Content-Type: application/json" >/dev/null 2>&1
        
        DNS_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
            "${AUTH_HEADERS[@]}" \
            -H "Content-Type: application/json" \
            --data "$DNS_DATA")
    else
        DNS_RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
            "${AUTH_HEADERS[@]}" \
            -H "Content-Type: application/json" \
            --data "$DNS_DATA")
    fi
else
    log_info "Creating new DNS record..."
    DNS_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
        "${AUTH_HEADERS[@]}" \
        -H "Content-Type: application/json" \
        --data "$DNS_DATA")
fi

if echo "$DNS_RESPONSE" | jq -e '.success' >/dev/null 2>&1; then
    log_success "DNS record configured successfully"
    DNS_NAME=$(echo "$DNS_RESPONSE" | jq -r '.result.name' 2>/dev/null || echo "$EXPLORER_DOMAIN")
    DNS_TARGET=$(echo "$DNS_RESPONSE" | jq -r '.result.content' 2>/dev/null || echo "$TARGET")
    DNS_PROXIED=$(echo "$DNS_RESPONSE" | jq -r '.result.proxied' 2>/dev/null || echo "true")
    log_info "  Name: $DNS_NAME"
    log_info "  Target: $DNS_TARGET"
    log_info "  Proxied: $DNS_PROXIED"
else
    ERROR=$(echo "$DNS_RESPONSE" | jq -r '.errors[0].message // "Unknown error"' 2>/dev/null || echo "API call failed")
    log_error "Failed to configure DNS: $ERROR"
    echo "$DNS_RESPONSE" | jq '.' 2>/dev/null || echo "$DNS_RESPONSE"
    exit 1
fi

# Step 6: Configure Tunnel Route
log_section
log_info "Step 6: Configuring Tunnel Route"
log_section

if [ -z "$CLOUDFLARE_ACCOUNT_ID" ] || [ "$CLOUDFLARE_ACCOUNT_ID" = "null" ]; then
    log_warn "Account ID not available - tunnel route must be configured manually"
    log_info "Configure in Cloudflare Zero Trust Dashboard:"
    echo "  1. Go to: https://one.dash.cloudflare.com/"
    echo "  2. Zero Trust → Networks → Tunnels"
    echo "  3. Select tunnel: $TUNNEL_ID"
    echo "  4. Configure → Public Hostnames → Add hostname"
    echo "  5. Subdomain: explorer, Domain: $DOMAIN"
    echo "  6. Service: http://$EXPLORER_IP:$EXPLORER_PORT"
else
    log_info "Configuring tunnel route via API..."
    
    # Get current tunnel configuration
    TUNNEL_CONFIG=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/cfd_tunnel/$TUNNEL_ID/configurations" \
        "${AUTH_HEADERS[@]}" \
        -H "Content-Type: application/json")
    
    # Build new ingress configuration
    NEW_CONFIG=$(jq -n \
        --arg hostname "$EXPLORER_DOMAIN" \
        --arg service "http://$EXPLORER_IP:$EXPLORER_PORT" \
        '{
            config: {
                ingress: [
                    {
                        hostname: $hostname,
                        service: $service
                    },
                    {
                        service: "http_status:404"
                    }
                ]
            }
        }')
    
    # Update tunnel configuration
    TUNNEL_UPDATE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/cfd_tunnel/$TUNNEL_ID/configurations" \
        "${AUTH_HEADERS[@]}" \
        -H "Content-Type: application/json" \
        --data "$NEW_CONFIG")
    
    if echo "$TUNNEL_UPDATE" | jq -e '.success' >/dev/null 2>&1; then
        log_success "Tunnel route configured successfully"
    else
        ERROR=$(echo "$TUNNEL_UPDATE" | jq -r '.errors[0].message // "Unknown error"' 2>/dev/null || echo "API call failed")
        log_warn "Tunnel route API configuration failed: $ERROR"
        log_info "Please configure manually in Cloudflare Zero Trust Dashboard"
    fi
fi

# Step 7: SSL/TLS Configuration (automatic with Cloudflare proxy)
log_section
log_info "Step 7: SSL/TLS Configuration"
log_section

log_info "SSL/TLS is automatically handled by Cloudflare when DNS is proxied"
log_success "SSL will be enabled automatically (Universal SSL)"

# Step 8: Verify Configuration
log_section
log_info "Step 8: Verifying Configuration"
log_section

log_info "Waiting for DNS propagation (10 seconds)..."
sleep 10

# Test DNS resolution
DNS_RESULT=$(dig +short "$EXPLORER_DOMAIN" 2>/dev/null | head -1 || echo "")
if [ -n "$DNS_RESULT" ]; then
    log_success "DNS resolves to: $DNS_RESULT"
    if echo "$DNS_RESULT" | grep -qE "^(104\.|172\.64\.|172\.65\.|172\.66\.|172\.67\.)"; then
        log_success "DNS points to Cloudflare (proxied correctly)"
    fi
else
    log_warn "DNS not resolving yet (may need more time)"
fi

# Test public URL
log_info "Testing public URL..."
PUBLIC_HTTP=$(curl -s -o /dev/null -w "%{http_code}" "https://$EXPLORER_DOMAIN/api/v2/stats" 2>&1)
if [ "$PUBLIC_HTTP" = "200" ]; then
    log_success "Public URL: HTTP 200 - Working!"
    PUBLIC_RESPONSE=$(curl -s "https://$EXPLORER_DOMAIN/api/v2/stats" 2>&1)
    if echo "$PUBLIC_RESPONSE" | grep -q -E "total_blocks|chain_id"; then
        log_success "Public API: Valid response"
        echo "$PUBLIC_RESPONSE" | jq -r '.total_blocks, .total_transactions, .total_addresses' 2>/dev/null || echo "$PUBLIC_RESPONSE" | head -5
    fi
elif [ "$PUBLIC_HTTP" = "404" ]; then
    log_warn "Public URL: HTTP 404 - May need more time for DNS/tunnel propagation"
elif [ "$PUBLIC_HTTP" = "502" ]; then
    log_warn "Public URL: HTTP 502 - Tunnel routing issue, check tunnel route configuration"
else
    log_warn "Public URL: HTTP $PUBLIC_HTTP"
fi

# Final Summary
echo ""
log_section
log_info "  CONFIGURATION SUMMARY"
log_section
echo ""

log_success "✓ Cloudflared service: Installed and running"
log_success "✓ Tunnel ID: $TUNNEL_ID"
log_success "✓ DNS Record: $EXPLORER_DOMAIN → $TARGET (🟠 Proxied)"
if [ -n "$CLOUDFLARE_ACCOUNT_ID" ]; then
    log_success "✓ Tunnel Route: Configured via API"
else
    log_warn "⚠ Tunnel Route: Manual configuration required"
fi
log_success "✓ SSL/TLS: Automatic (Cloudflare Universal SSL)"

echo ""
log_info "Configuration complete!"
log_info ""
log_info "Access your explorer at:"
echo "  https://$EXPLORER_DOMAIN"
echo ""
log_info "If public URL is not working yet, wait 1-5 minutes for DNS propagation"
echo ""

