#!/bin/bash
# setup-dns-records.sh
# Creates DNS records for Proxmox instances using Cloudflare API

set -euo pipefail

# Load environment variables from .env if it exists
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "${SCRIPT_DIR}/../.env" ]; then
    source "${SCRIPT_DIR}/../.env"
fi

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

# Configuration
DOMAIN="${DOMAIN:-sankofa.nexus}"
ZONE_ID="${CLOUDFLARE_ZONE_ID:-}"
# Support both API Token and Global API Key + Email
API_TOKEN="${CLOUDFLARE_API_TOKEN:-}"
API_KEY="${CLOUDFLARE_API_KEY:-}"
API_EMAIL="${CLOUDFLARE_EMAIL:-}"

# Instance configurations
declare -A INSTANCES=(
    ["ml110-01"]="192.168.11.10"
    ["r630-01"]="192.168.11.11"
)

log() {
    echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}

error() {
    echo -e "${RED}[ERROR]${NC} $1" >&2
    exit 1
}

warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

check_requirements() {
    # Check if we have either API Token or Global API Key + Email
    if [ -z "$API_TOKEN" ] && [ -z "$API_KEY" ]; then
        error "Either CLOUDFLARE_API_TOKEN or CLOUDFLARE_API_KEY must be set"
    fi
    
    if [ -z "$API_TOKEN" ] && [ -z "$API_EMAIL" ]; then
        error "If using CLOUDFLARE_API_KEY, CLOUDFLARE_EMAIL must also be set"
    fi
    
    if ! command -v curl &> /dev/null; then
        error "curl is required but not installed"
    fi
    
    if ! command -v jq &> /dev/null; then
        error "jq is required but not installed"
    fi
    
    # Try to get zone ID if not provided
    if [ -z "$ZONE_ID" ]; then
        get_zone_id
    fi
}

get_zone_id() {
    if [ -z "$ZONE_ID" ]; then
        log "Getting zone ID for ${DOMAIN}..."
        
        if [ -n "$API_TOKEN" ]; then
            # Use API Token
            ZONE_ID=$(curl -s -X GET \
                -H "Authorization: Bearer ${API_TOKEN}" \
                -H "Content-Type: application/json" \
                "https://api.cloudflare.com/client/v4/zones?name=${DOMAIN}" | \
                jq -r '.result[0].id')
        elif [ -n "$API_KEY" ] && [ -n "$API_EMAIL" ]; then
            # Use Global API Key + Email
            ZONE_ID=$(curl -s -X GET \
                -H "X-Auth-Email: ${API_EMAIL}" \
                -H "X-Auth-Key: ${API_KEY}" \
                -H "Content-Type: application/json" \
                "https://api.cloudflare.com/client/v4/zones?name=${DOMAIN}" | \
                jq -r '.result[0].id')
        else
            error "Cannot get Zone ID: No authentication method available"
        fi
        
        if [ "$ZONE_ID" == "null" ] || [ -z "$ZONE_ID" ]; then
            error "Failed to get zone ID for ${DOMAIN}"
        fi
        
        log "Zone ID: ${ZONE_ID}"
        export CLOUDFLARE_ZONE_ID="$ZONE_ID"
    fi
}

create_a_record() {
    local name=$1
    local ip=$2
    local comment=$3
    
    log "Creating A record: ${name}.${DOMAIN} → ${ip}"
    
    local response
    if [ -n "$API_TOKEN" ]; then
        response=$(curl -s -X POST \
            -H "Authorization: Bearer ${API_TOKEN}" \
            -H "Content-Type: application/json" \
            "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
            -d "{
                \"type\": \"A\",
                \"name\": \"${name}\",
                \"content\": \"${ip}\",
                \"ttl\": 300,
                \"comment\": \"${comment}\",
                \"proxied\": false
            }")
    else
        response=$(curl -s -X POST \
            -H "X-Auth-Email: ${API_EMAIL}" \
            -H "X-Auth-Key: ${API_KEY}" \
            -H "Content-Type: application/json" \
            "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
            -d "{
                \"type\": \"A\",
                \"name\": \"${name}\",
                \"content\": \"${ip}\",
                \"ttl\": 300,
                \"comment\": \"${comment}\",
                \"proxied\": false
            }")
    fi
    
    local success=$(echo "$response" | jq -r '.success')
    local record_id=$(echo "$response" | jq -r '.result.id // empty')
    
    if [ "$success" == "true" ] && [ -n "$record_id" ]; then
        log "✓ A record created: ${name}.${DOMAIN} (ID: ${record_id})"
        return 0
    else
        local errors=$(echo "$response" | jq -r '.errors[].message // "Unknown error"' | head -1)
        warn "Failed to create A record: ${errors}"
        return 1
    fi
}

create_cname_record() {
    local name=$1
    local target=$2
    local comment=$3
    
    log "Creating CNAME record: ${name}.${DOMAIN} → ${target}"
    
    local response
    if [ -n "$API_TOKEN" ]; then
        response=$(curl -s -X POST \
            -H "Authorization: Bearer ${API_TOKEN}" \
            -H "Content-Type: application/json" \
            "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
            -d "{
                \"type\": \"CNAME\",
                \"name\": \"${name}\",
                \"content\": \"${target}\",
                \"ttl\": 300,
                \"comment\": \"${comment}\",
                \"proxied\": false
            }")
    else
        response=$(curl -s -X POST \
            -H "X-Auth-Email: ${API_EMAIL}" \
            -H "X-Auth-Key: ${API_KEY}" \
            -H "Content-Type: application/json" \
            "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
            -d "{
                \"type\": \"CNAME\",
                \"name\": \"${name}\",
                \"content\": \"${target}\",
                \"ttl\": 300,
                \"comment\": \"${comment}\",
                \"proxied\": false
            }")
    fi
    
    local success=$(echo "$response" | jq -r '.success')
    local record_id=$(echo "$response" | jq -r '.result.id // empty')
    
    if [ "$success" == "true" ] && [ -n "$record_id" ]; then
        log "✓ CNAME record created: ${name}.${DOMAIN} (ID: ${record_id})"
        return 0
    else
        local errors=$(echo "$response" | jq -r '.errors[].message // "Unknown error"' | head -1)
        warn "Failed to create CNAME record: ${errors}"
        return 1
    fi
}

check_record_exists() {
    local name=$1
    local type=$2
    
    local response
    if [ -n "$API_TOKEN" ]; then
        response=$(curl -s -X GET \
            -H "Authorization: Bearer ${API_TOKEN}" \
            -H "Content-Type: application/json" \
            "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${name}.${DOMAIN}&type=${type}")
    else
        response=$(curl -s -X GET \
            -H "X-Auth-Email: ${API_EMAIL}" \
            -H "X-Auth-Key: ${API_KEY}" \
            -H "Content-Type: application/json" \
            "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${name}.${DOMAIN}&type=${type}")
    fi
    
    local count=$(echo "$response" | jq -r '.result | length')
    
    if [ "$count" -gt 0 ]; then
        return 0  # Record exists
    else
        return 1  # Record does not exist
    fi
}

setup_instance_dns() {
    local instance_name=$1
    local ip=$2
    
    local fqdn="${instance_name}.${DOMAIN}"
    
    # Create A record
    if check_record_exists "$instance_name" "A"; then
        warn "A record for ${fqdn} already exists, skipping..."
    else
        create_a_record "$instance_name" "$ip" "Proxmox Instance - ${instance_name}"
    fi
    
    # Create API CNAME
    if check_record_exists "${instance_name}-api" "CNAME"; then
        warn "CNAME record for ${instance_name}-api.${DOMAIN} already exists, skipping..."
    else
        create_cname_record "${instance_name}-api" "$fqdn" "Proxmox ${instance_name} API endpoint"
    fi
    
    # Create metrics CNAME
    if check_record_exists "${instance_name}-metrics" "CNAME"; then
        warn "CNAME record for ${instance_name}-metrics.${DOMAIN} already exists, skipping..."
    else
        create_cname_record "${instance_name}-metrics" "$fqdn" "Proxmox ${instance_name} metrics endpoint"
    fi
}

main() {
    log "Setting up DNS records for Proxmox instances"
    log "Domain: ${DOMAIN}"
    
    check_requirements
    get_zone_id
    
    log ""
    log "Creating DNS records for ${#INSTANCES[@]} instances..."
    log ""
    
    for instance_name in "${!INSTANCES[@]}"; do
        setup_instance_dns "$instance_name" "${INSTANCES[$instance_name]}"
        echo ""
    done
    
    log "DNS setup complete!"
    log ""
    log "Created records:"
    for instance_name in "${!INSTANCES[@]}"; do
        echo "  • ${instance_name}.${DOMAIN} → ${INSTANCES[$instance_name]}"
        echo "  • ${instance_name}-api.${DOMAIN} → ${instance_name}.${DOMAIN}"
        echo "  • ${instance_name}-metrics.${DOMAIN} → ${instance_name}.${DOMAIN}"
    done
}

main "$@"

