#!/command/with-contenv bash

# Get verbosity level (0=minimal, 1=normal, 2=verbose)
VERBOSITY="${ALIASVAULT_VERBOSITY:-0}"

# Copy certificates to nginx directory (they were created during init)
mkdir -p /etc/nginx/ssl
cp /certificates/ssl/* /etc/nginx/ssl/ 2>/dev/null || true

# Create SSL configuration file
cat > /etc/nginx/ssl.conf << "SSLEOF"
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozTLS:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
SSLEOF

# Configure nginx based on FORCE_HTTPS_REDIRECT environment variable
FORCE_HTTPS_REDIRECT=${FORCE_HTTPS_REDIRECT:-false}
if [[ "${FORCE_HTTPS_REDIRECT}" == "true" ]]; then
    echo "Configuring nginx with HTTPS-only (443) - redirects HTTP to HTTPS"
    cp /etc/nginx/nginx-443.conf /etc/nginx/nginx.conf
else
    echo "Configuring nginx with HTTP and HTTPS support (80+443)"
    cp /etc/nginx/nginx-80-443.conf /etc/nginx/nginx.conf
fi

# Build the geo-block rules for the /admin IP allowlist from ADMIN_IP_ALLOWLIST.
# Empty -> "default 0;" (everyone allowed). "private" -> default-deny with
# loopback + RFC1918 carved out. Anything else is treated as a comma-separated
# list of CIDRs/IPs (loopback is always allowed). Tokens that don't look like
# an IPv4/IPv6 address or CIDR are skipped with a warning so a typo can't
# crash-loop nginx; if no valid tokens remain we fail closed (deny everything
# except loopback). When the resulting $admin_block is 1, the /admin location
# quietly routes the request to the client app via @admin_fallback rather than
# emitting a 403/404.
is_valid_cidr() {
    case "$1" in
        *:*)
            printf '%s' "$1" | grep -Eq '^[0-9a-fA-F:]+(/[0-9]{1,3})?$'
            ;;
        *)
            printf '%s' "$1" | grep -Eq '^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]{1,2})?$'
            ;;
    esac
}

build_admin_ip_geo_rules() {
    local raw="${ADMIN_IP_ALLOWLIST:-}"
    case "$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]')" in
        "")
            printf '%s' "default 0;"
            ;;
        private)
            printf '%s' "default 1; 127.0.0.0/8 0; 10.0.0.0/8 0; 172.16.0.0/12 0; 192.168.0.0/16 0;"
            ;;
        *)
            local out="default 1; 127.0.0.0/8 0;"
            local valid=0
            local IFS=','
            for cidr in $raw; do
                cidr=$(printf '%s' "$cidr" | tr -d '[:space:]')
                [ -z "$cidr" ] && continue
                if is_valid_cidr "$cidr"; then
                    out="$out $cidr 0;"
                    valid=$((valid + 1))
                else
                    printf 'warning: ADMIN_IP_ALLOWLIST: ignoring invalid CIDR/IP %s\n' "$cidr" >&2
                fi
            done
            if [ "$valid" -eq 0 ]; then
                printf 'warning: ADMIN_IP_ALLOWLIST has no valid entries; /admin will fall through to the client app for all non-loopback traffic\n' >&2
            fi
            printf '%s' "$out"
            ;;
    esac
}

ADMIN_IP_GEO_RULES_VALUE=$(build_admin_ip_geo_rules)
sed -i "s|__ADMIN_IP_GEO_RULES__|${ADMIN_IP_GEO_RULES_VALUE}|g" /etc/nginx/nginx.conf

# Build the set_real_ip_from directives from TRUSTED_PROXIES. These tell nginx
# which upstream proxies it should accept the X-Forwarded-For header from when
# determining the real client IP. Empty -> RFC1918 (backwards-compatible
# default). "none" -> no directives (raw $remote_addr is always used). Otherwise
# treated as a comma-separated list of CIDRs/IPs; invalid tokens are skipped
# with a warning so a typo can't crash-loop nginx, and if no valid tokens
# remain we emit no directives (equivalent to "none").
build_trusted_proxies_directives() {
    local raw="${TRUSTED_PROXIES:-}"
    case "$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]')" in
        "")
            printf '%s' "set_real_ip_from 10.0.0.0/8; set_real_ip_from 172.16.0.0/12; set_real_ip_from 192.168.0.0/16;"
            ;;
        none)
            printf '%s' ""
            ;;
        *)
            local out=""
            local valid=0
            local IFS=','
            for cidr in $raw; do
                cidr=$(printf '%s' "$cidr" | tr -d '[:space:]')
                [ -z "$cidr" ] && continue
                if is_valid_cidr "$cidr"; then
                    if [ -z "$out" ]; then
                        out="set_real_ip_from $cidr;"
                    else
                        out="$out set_real_ip_from $cidr;"
                    fi
                    valid=$((valid + 1))
                else
                    printf 'warning: TRUSTED_PROXIES: ignoring invalid CIDR/IP %s\n' "$cidr" >&2
                fi
            done
            if [ "$valid" -eq 0 ]; then
                printf 'warning: TRUSTED_PROXIES has no valid entries; X-Forwarded-For will be ignored from all upstreams\n' >&2
            fi
            printf '%s' "$out"
            ;;
    esac
}

TRUSTED_PROXIES_VALUE=$(build_trusted_proxies_directives)
sed -i "s|__TRUSTED_PROXIES__|${TRUSTED_PROXIES_VALUE}|g" /etc/nginx/nginx.conf

echo "Starting Nginx reverse proxy..."

# Set nginx error log level based on verbosity
if [ "$VERBOSITY" -ge 2 ]; then
    # Verbose: info level
    exec nginx -g "daemon off; error_log /dev/stderr info;"
elif [ "$VERBOSITY" -ge 1 ]; then
    # Normal: warn level
    exec nginx -g "daemon off; error_log /dev/stderr warn;"
else
    # Minimal: error level only
    exec nginx -g "daemon off; error_log /dev/stderr error;"
fi