#!/usr/bin/env bash
set -euo pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
INVENTORY_FILE="${HOMELAB_INVENTORY_FILE:-${REPO_ROOT}/homelab.yml}"
FORMAT="${1:-text}"

inventory() {
    local path="$1"
    local fallback="$2"

    if command -v ruby >/dev/null 2>&1 && [ -f "$INVENTORY_FILE" ]; then
        value="$(
            ruby -ryaml -e '
              data = YAML.load_file(ARGV[0])
              value = ARGV[1].split(".").reduce(data) { |memo, key| memo.respond_to?(:[]) ? memo[key] : nil }
              puts value if value.is_a?(String) || value.is_a?(Integer)
            ' "$INVENTORY_FILE" "$path" 2>/dev/null || true
        )"
        if [ -n "$value" ]; then
            printf '%s\n' "$value"
            return 0
        fi
    fi

    printf '%s\n' "$fallback"
}

domain="$(inventory domain.base lab2025.duckdns.org)"
debian="$(inventory hosts.debian.lan_ip 192.168.100.73)"
debian_ts="$(inventory hosts.debian.tailscale_ip 100.85.138.30)"
rpi="$(inventory hosts.rpi4.lan_ip 192.168.100.89)"
oci="$(inventory hosts.oci_edge.public_ip 132.145.170.74)"
oci_ts="$(inventory hosts.oci_edge.tailscale_ip 100.118.255.19)"
pimox="$(inventory hosts.opi5_pimox.lan_ip 192.168.100.80)"
traefik="$(inventory network.metallb.traefik_ip 192.168.100.240)"
registry="$(inventory services.local_registry.endpoint 192.168.100.73:30500)"
gitea_http="$(inventory services.gitea.http_port 3000)"
gitea_ssh="$(inventory services.gitea.ssh_port 32222)"
pihole_web="$(inventory services.rpi_dns.pihole_web_port 8081)"
kuma="$(inventory services.rpi_dns.uptime_kuma_port 3001)"

if [ "$FORMAT" = "--dot" ] || [ "$FORMAT" = "dot" ]; then
    cat <<EOF
digraph homelab {
  rankdir=LR;
  "Internet" -> "OCI edge ${oci}";
  "OCI edge ${oci}" -> "Traefik ${traefik}";
  "OCI edge ${oci}" -> "Debian Tailscale ${debian_ts}";
  "Debian ${debian}" -> "Gitea :${gitea_http}/git";
  "Debian ${debian}" -> "Local registry ${registry}";
  "Debian ${debian}" -> "Kubernetes control plane";
  "Debian ${debian}" -> "Pimox ${pimox}";
  "Pimox ${pimox}" -> "Worker VMs";
  "Worker VMs" -> "Kubernetes apps";
  "Kubernetes apps" -> "Traefik ${traefik}";
  "Gitea :${gitea_http}/git" -> "Argo CD";
  "Argo CD" -> "Kubernetes apps";
  "Clients" -> "Pi-hole ${rpi}:53";
  "Pi-hole ${rpi}:53" -> "Unbound";
  "Pi-hole ${rpi}:53" -> "Public DNS fallback";
  "Uptime Kuma ${rpi}:${kuma}" -> "Public URLs";
  "Uptime Kuma ${rpi}:${kuma}" -> "LAN services";
}
EOF
    exit 0
fi

cat <<EOF
Homelab dependency map
======================

Public entry
  Internet
    -> ${domain}
    -> OCI edge ${oci} / tailscale ${oci_ts}
    -> Traefik LoadBalancer ${traefik}
    -> Kubernetes ingress routes
    -> website, demos, Heimdall, observability, Argo CD, arr routes

Git and automation
  Debian ${debian}
    -> Gitea HTTP :${gitea_http}/git and SSH :${gitea_ssh}
    -> Gitea Actions runner
    -> local registry ${registry}
    -> jeannie orchestration
  Gitea repository
    -> Argo CD applications
    -> Kubernetes manifests under apps/
    -> edge/provisioning/cluster/platform Terraform stacks

Cluster foundation
  Debian ${debian}
    -> kubeadm control plane
    -> container registry
    -> provisioning HTTP/TFTP
  Orange Pi Pimox ${pimox}
    -> worker VM template
    -> worker VM clones
    -> Kubernetes worker capacity

DNS and always-on health
  Clients and lab hosts
    -> RPi4 Pi-hole ${rpi}:53
    -> Unbound resolver
    -> public fallback DNS if Unbound is unhealthy
  RPi4
    -> Pi-hole web ${rpi}:${pihole_web}
    -> Uptime Kuma ${rpi}:${kuma}
    -> monitors public URLs, LAN services, DNS, Traefik, Gitea, arr

Observability and operations
  Prometheus stack
    -> nodes, pods, Traefik, website probes, Gitea/Pi-hole scrape coverage
    -> homelab-alerts
    -> Grafana dashboards
  jeannie status
    -> host/bootstrap checks
    -> local services
    -> RPi DNS and Kuma
    -> Pimox and Kubernetes
    -> platform/apps
    -> edge/public URLs

Security learning loop
  security-lab namespace
    -> isolated OWASP practice targets
    -> ZAP/nuclei/trivy/lynis helper commands
    -> report-only findings before manual fixes

Use './jeannie map --dot' to emit a Graphviz DOT version.
EOF
