#!/bin/bash

# Per-port Traefik subdomain/host writer.
#
# Companion to traefik_port_middlewares.sh. Where that stamps a per-port
# MIDDLEWARE_TAG_<i>, this stamps a per-port DOMAINSUBNAME_TAG_<i> holding the
# fully-qualified host for that port's Traefik router, derived from the port's
# `subdomain` column (the 11th field of the 12-col PORT format).
#
# A single container can expose any number of hosts — one per Traefik-managed port.
#
#   subdomain ""  | "@" | "root"   -> <domain>                 (apex / root of domain)
#   subdomain "vault"              -> vault.<domain>           (single label)
#   subdomain "admin.headscale"    -> admin.headscale.<domain> (multi-level allowed)
#
# Index scheme matches traefik_port_middlewares.sh exactly: i walks every
# parsed port (0-based), idx = i+1 is the 1-based position used in the tag
# suffix, and only Traefik-managed ports (traefik=true) are stamped — so a
# port's MIDDLEWARE_TAG_<idx> and DOMAINSUBNAME_TAG_<idx> always line up on the
# same router.
tagsProcessorPortSubdomains()
{
    local file="$1"
    local app_name="$2"

    if [[ -z "$file" || -z "$app_name" ]]; then
        return 0
    fi

    local count=${#port_service_names[@]}
    local i=0
    while [[ $i -lt $count ]]; do
        local idx=$((i + 1))
        local p_traefik="${port_traefik_managed[$i]}"
        local p_sub="${port_subdomains[$i]}"

        if [[ "$p_traefik" == "true" ]]; then
            local host
            if [[ "$p_sub" == "@" || "$p_sub" == "root" ]]; then
                host="${domain_full}"                 # apex / root of the domain (explicit only)
            elif [[ -n "$p_sub" ]]; then
                host="${p_sub}.${domain_full}"        # subdomain (single or multi-level)
            else
                host="${app_name}.${domain_full}"     # no subdomain set -> app-name default
            fi
            tagsManagerUpdateUniversalTag "$file" "DOMAINSUBNAME_TAG_${idx}" "$host"
        fi
        i=$((i + 1))
    done
}

# Comments out the Traefik router block for any port that is NOT Traefik-managed
# (non-public, metrics-only, or a slot with no router at all), so an unfilled
# DOMAINSUBNAME_DATA_<n> placeholder can never reach a live compose. Each router
# is wrapped in  # TRAEFIK_PORT_<n>_BEGIN ... # TRAEFIK_PORT_<n>_END  markers;
# this mirrors the GLUETUN_OFF region-commenting in tags_processor_network_mode.sh.
tagsProcessorPortRouterBlocks()
{
    local file="$1"
    local app_name="$2"
    if [[ -z "$file" || ! -f "$file" ]]; then
        return 0
    fi

    # Space-padded list of 1-based indices of Traefik-managed ports, e.g. " 1 3 ".
    local active=" "
    local count=${#port_service_names[@]}
    local i=0
    while [[ $i -lt $count ]]; do
        [[ "${port_traefik_managed[$i]}" == "true" ]] && active+="$((i + 1)) "
        i=$((i + 1))
    done

    local tmp="${file}.routers.$$"
    runFileOp awk -v active="$active" '
        BEGIN { off = 0 }
        /#[[:space:]]*TRAEFIK_PORT_[0-9]+_BEGIN/ {
            match($0, /TRAEFIK_PORT_[0-9]+/); key = substr($0, RSTART, RLENGTH)
            sub(/TRAEFIK_PORT_/, "", key)
            off = (index(active, " " key " ") > 0) ? 0 : 1   # off=1 -> comment the block
            print; next
        }
        /#[[:space:]]*TRAEFIK_PORT_[0-9]+_END/ { off = 0; print; next }
        {
            if (off == 1 && $0 !~ /^[[:space:]]*#/) {
                match($0, /^[[:space:]]*/)
                indent = substr($0, RSTART, RLENGTH)
                rest = substr($0, RLENGTH + 1)
                print indent "# " rest
                next
            }
            print
        }
    ' "$file" | runFileWrite "$tmp" >/dev/null
    runFileOp mv "$tmp" "$file"
}
