#!/bin/bash
set -e

# Source debconf library
. /usr/share/debconf/confmodule

detect_internal_ip() {
    # Try multiple methods to get the most reliable internal IP
    local ip=""

    # Method 1: Get IP from default route
    ip=$(ip route get 1.1.1.1 2>/dev/null | grep -oP 'src \K[0-9.]+' 2>/dev/null | head -1)

    # Method 2: If that fails, get first non-localhost IP
    if [ -z "$ip" ]; then
        ip=$(ip -4 addr show 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}' 2>/dev/null | grep -v '127.0.0.1' | head -1)
    fi

    # Method 3: Try hostname -I
    if [ -z "$ip" ]; then
        ip=$(hostname -I 2>/dev/null | awk '{print $1}')
    fi

    echo "${ip:-127.0.0.1}"
}

# Get IMDSv2 token (required, IMDSv1 is disabled on modern EC2 instances)
get_imds_token() {
    curl -s -m 2 -X PUT "http://169.254.169.254/latest/api/token" \
        -H "X-aws-ec2-metadata-token-ttl-seconds: 300" 2>/dev/null || echo ""
}

is_ec2_instance() {
    # Use IMDSv2 to detect EC2 instance (IMDSv1 is disabled on modern instances)
    local token=$(get_imds_token)
    if [ -z "$token" ]; then
        return 1  # Not EC2 or IMDS not available
    fi

    local instance_id=$(curl -s -m 2 -H "X-aws-ec2-metadata-token: $token" \
        http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null || echo "")
    if [ -n "$instance_id" ] && [[ "$instance_id" == i-* ]]; then
        return 0  # Is EC2
    fi

    return 1  # Not EC2
}

get_ec2_metadata() {
    local metadata_item="$1"
    local token=$(get_imds_token)
    if [ -z "$token" ]; then
        echo ""
        return
    fi
    curl -s -m 2 -H "X-aws-ec2-metadata-token: $token" \
        "http://169.254.169.254/latest/meta-data/$metadata_item" 2>/dev/null || echo ""
}

detect_public_ip() {
    local public_ip=""

    # First, check if we're on EC2
    if is_ec2_instance; then
        # Try to get public IP from EC2 metadata
        public_ip=$(get_ec2_metadata "public-ipv4")
        if [ -n "$public_ip" ] && [[ "$public_ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
            echo "$public_ip"
            return
        fi
    fi

    # Fallback to external services
    # Only try if we have internet connectivity
    if ping -c 1 -W 1 1.1.1.1 >/dev/null 2>&1; then
        # Try multiple services with short timeout
        for service in "https://checkip.amazonaws.com" "https://api.ipify.org" "https://ipinfo.io/ip"; do
            public_ip=$(curl -s --max-time 2 "$service" 2>/dev/null | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$')
            if [ -n "$public_ip" ]; then
                break
            fi
        done
    fi

    echo "$public_ip"
}

# Set defaults
db_set joblet/server_address "0.0.0.0"
db_set joblet/server_port "50051"

# Detect internal IP
DETECTED_INTERNAL_IP=$(detect_internal_ip)
db_set joblet/cert_internal_ip "$DETECTED_INTERNAL_IP"

# Simple EC2 detection
IS_EC2=false
if is_ec2_instance; then
    IS_EC2=true

    # Get EC2 info if available
    EC2_INSTANCE_ID=$(get_ec2_metadata "instance-id")
    EC2_PUBLIC_HOSTNAME=$(get_ec2_metadata "public-hostname")
    EC2_REGION=$(get_ec2_metadata "placement/availability-zone" | sed 's/[a-z]$//')

    # Save for later use
    cat > /tmp/joblet-ec2-info << EOF
IS_EC2=true
EC2_INSTANCE_ID="$EC2_INSTANCE_ID"
EC2_PUBLIC_HOSTNAME="$EC2_PUBLIC_HOSTNAME"
EC2_REGION="$EC2_REGION"
EOF
fi

# Detect public IP
DETECTED_PUBLIC_IP=$(detect_public_ip)
if [ -n "$DETECTED_PUBLIC_IP" ]; then
    if [ "$IS_EC2" = true ]; then
        # Pre-fill for EC2
        db_set joblet/cert_public_ip "$DETECTED_PUBLIC_IP"
        if [ -n "$EC2_PUBLIC_HOSTNAME" ]; then
            db_set joblet/cert_domain "$EC2_PUBLIC_HOSTNAME"
        fi
    fi
fi

# PAGE 1: gRPC Server Configuration
db_beginblock
db_input high joblet/server_address || true
db_input high joblet/server_port || true
db_endblock
db_go || true

# PAGE 2: Certificate Configuration
db_beginblock
db_input high joblet/cert_internal_ip || true
db_input medium joblet/cert_public_ip || true
db_input medium joblet/cert_domain || true
db_endblock
db_go || true

# Get all the values for postinst
db_get joblet/server_address
SERVER_ADDRESS="$RET"

db_get joblet/server_port
SERVER_PORT="$RET"

db_get joblet/cert_internal_ip
CERT_INTERNAL_IP="$RET"

db_get joblet/cert_public_ip
CERT_PUBLIC_IP="$RET"

db_get joblet/cert_domain
CERT_DOMAIN="$RET"

# Build additional names list for certificate generation
ADDITIONAL_NAMES=""

# Always include localhost
ADDITIONAL_NAMES="localhost"

# Add internal IP if different from bind address
if [ -n "$CERT_INTERNAL_IP" ] && [ "$CERT_INTERNAL_IP" != "$SERVER_ADDRESS" ] && [ "$SERVER_ADDRESS" != "0.0.0.0" ]; then
    ADDITIONAL_NAMES="$ADDITIONAL_NAMES,$CERT_INTERNAL_IP"
fi

# Add public IP if provided
if [ -n "$CERT_PUBLIC_IP" ]; then
    ADDITIONAL_NAMES="$ADDITIONAL_NAMES,$CERT_PUBLIC_IP"
fi

# Add domains if provided
if [ -n "$CERT_DOMAIN" ]; then
    ADDITIONAL_NAMES="$ADDITIONAL_NAMES,$CERT_DOMAIN"
fi

# Store configuration for postinst
cat > /tmp/joblet-install-config << EOF
JOBLET_SERVER_ADDRESS="$SERVER_ADDRESS"
JOBLET_SERVER_PORT="$SERVER_PORT"
JOBLET_CERT_INTERNAL_IP="$CERT_INTERNAL_IP"
JOBLET_CERT_PUBLIC_IP="$CERT_PUBLIC_IP"
JOBLET_CERT_DOMAIN="$CERT_DOMAIN"
JOBLET_ADDITIONAL_NAMES="$ADDITIONAL_NAMES"
# Primary certificate address (for certificate CN)
# Use internal IP as primary, as it's always available
JOBLET_CERT_PRIMARY="$CERT_INTERNAL_IP"
EOF

# Show summary
echo "Configuration Summary:"
echo "  gRPC Server: $SERVER_ADDRESS:$SERVER_PORT"
echo "  Certificate IPs: $CERT_INTERNAL_IP${CERT_PUBLIC_IP:+, $CERT_PUBLIC_IP}"
echo "  Certificate Domains: ${CERT_DOMAIN:-none}"

exit 0