#!/bin/sh
# forge-dns-render — manage cloud DX forge shortnames (mcforge for magic-civilization,
# ctforge for cocottetech/lilithplatform, ...) in /etc/hosts as part of the shared
# net-tools infra installers for dev DX.
#
# Reads current FORGE_IP from ~/.vault/*_forge_creds (maintained by the per-project
# ./run forge:up / forge:dns in @magic-civilization and @cocottetech).
#
# Emits a marked, idempotently-replaceable block. `net sync` (and manual
# mesh-hosts-render + host-apply) now also converges the DX forge shortcuts.
# Per-project `./run forge:dns` prefers this central renderer when available.
#
# The block lives at the bottom (after the prepended mesh-hosts fleet block).
# Loose hand-managed lines for these names are adopted (removed) on --install.
#
# Usage:
#   forge-dns-render            # print the block (default)
#   forge-dns-render --install  # splice/replace in /etc/hosts (sudo)
#   forge-dns-render --diff     # show what --install would do
#
# Exit codes match mesh-hosts-render (0 success, 2 needs root).

set -eu

mode=print
case "${1:-}" in
    ""|--print) mode=print ;;
    --install)  mode=install ;;
    --diff)     mode=diff ;;
    *) echo "forge-dns-render: unknown arg '$1' (use --print|--install|--diff)" >&2; exit 1 ;;
esac

BEGIN='# >>> dx-forges (managed by net-tools/bin/forge-dns-render)'
END='# <<< dx-forges'
HOSTS_FILE=/etc/hosts
VAULT_DIR="${HOME}/.vault"

# Map vault basename -> the short hostname users type for :3000
map_short() {
    case "$1" in
        mc_forge_creds)      echo mcforge ;;
        cocotte_forge_creds) echo ctforge ;;
        *)                   echo "" ;;
    esac
}

render_block() {
    printf '%s\n' "$BEGIN"
    printf '# Cloud DX Forgejo /etc/hosts shortcuts (mcforge, ctforge, ...).\n'
    printf '# IPs from ~/.vault/*_forge_creds FORGE_IP (refreshed by project ./run forge:up).\n'
    printf '# Re-run after any forge:up (droplet gets a new IP on restore-from-snapshot).\n'
    printf '# http://<name>:3000  — also kept fresh by net-tools infra (net sync).\n'
    had=0
    for f in "$VAULT_DIR"/mc_forge_creds "$VAULT_DIR"/cocotte_forge_creds; do
        [ -f "$f" ] || continue
        base=$(basename "$f")
        short=$(map_short "$base")
        [ -n "$short" ] || continue
        ip=$(grep -E '^FORGE_IP=' "$f" 2>/dev/null | head -1 | cut -d= -f2- | tr -d ' \t\r\n')
        [ -n "$ip" ] || continue
        printf '%s\t%s\n' "$ip" "$short"
        had=1
    done
    if [ "$had" -eq 0 ]; then
        printf '# (no active DX forges — ./run forge:up in the relevant project(s) first)\n'
    fi
    printf '%s\n' "$END"
}

block=$(render_block)

if [ "$mode" = "print" ]; then
    printf '%s\n' "$block"
    exit 0
fi

# All shortnames we own (for adoption of stale loose lines).
managed=$(printf '%s\n' "$block" | awk '!/^#/ && NF >= 2 { for (i = 2; i <= NF; i++) print $i }' | sort -u | tr '\n' ' ')

current=$(cat "$HOSTS_FILE" 2>/dev/null || true)

# Strip any previous copy of our block.
stripped=$(printf '%s\n' "$current" | awk -v b="$BEGIN" -v e="$END" '
    $0 == b { skip = 1 }
    skip != 1 { print }
    $0 == e { skip = 0 }
')

# Adopt (remove) any loose lines or name tokens that match our managed forges.
# (Same policy as mesh-hosts-render: the tool owns these names now.)
stripped=$(printf '%s\n' "$stripped" | awk -v names="$managed" '
    BEGIN { n = split(names, a, /[[:space:]]+/); for (i = 1; i <= n; i++) if (a[i] != "") set[a[i]] = 1 }
    /^[[:space:]]*#/ || NF < 2 { print; next }
    {
        kept = ""; removed = 0
        for (i = 2; i <= NF; i++) {
            if ($i in set) removed++
            else kept = kept " " $i
        }
        if (removed == 0) { print; next }
        if (kept == "") next
        print $1 kept
    }
')

# Trim leading/trailing blank lines that accumulate from repeated splices.
stripped=$(printf '%s\n' "$stripped" | awk 'NF {f=1; p=NR} f {l[NR]=$0} END {for(i=1;i<=p;i++) if (i in l) print l[i]}')

# Append the dx-forges block at the bottom (mesh-hosts block is prepended at top).
new=$(printf '%s\n\n%s\n' "$stripped" "$block")

if [ "$mode" = "diff" ]; then
    if command -v diff >/dev/null 2>&1; then
        printf '%s\n' "$new" | diff -u "$HOSTS_FILE" - || true
    else
        printf '%s\n' "$new"
    fi
    exit 0
fi

# --install
if printf '%s\n' "$new" | cmp -s - "$HOSTS_FILE"; then
    echo "forge-dns-render: $HOSTS_FILE already up to date"
    exit 0
fi

SUDO=""
if [ "$(id -u)" -ne 0 ]; then
    if command -v sudo >/dev/null 2>&1; then
        SUDO="sudo"
    else
        echo "forge-dns-render: --install needs root" >&2
        exit 2
    fi
fi

printf '%s\n' "$new" | $SUDO tee "$HOSTS_FILE" >/dev/null
echo "forge-dns-render: updated $HOSTS_FILE"
