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

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
KUBECONFIG_PATH="${KUBECONFIG:-${LAB_KUBECONFIG_PATH:-/home/jv/.kube/config}}"
PROFILE_FILE="${HOMELAB_RESOURCE_RECOMMENDATIONS:-${REPO_ROOT}/infra/resource-recommendations.yml}"
NAMESPACE="${1:-}"
PODS_JSON=""

cleanup() {
    if [ -n "$PODS_JSON" ] && [ -f "$PODS_JSON" ]; then
        rm -f "$PODS_JSON"
    fi
}
trap cleanup EXIT

usage() {
    cat <<'EOF'
Usage: ./jeannie capacity-limits [namespace]

Recommend Kubernetes requests/limits for containers missing them. This command
prints YAML snippets only; it does not edit manifests.
EOF
}

case "${1:-}" in
    -h|--help|help)
        usage
        exit 0
        ;;
esac

if ! command -v kubectl >/dev/null 2>&1; then
    echo "kubectl is required." >&2
    exit 1
fi
if [ ! -s "$KUBECONFIG_PATH" ]; then
    echo "kubeconfig is missing: $KUBECONFIG_PATH" >&2
    exit 1
fi

PODS_JSON="$(mktemp "${TMPDIR:-/tmp}/jeannie-capacity-limits.XXXXXX")"
if [ -n "$NAMESPACE" ]; then
    kubectl --kubeconfig "$KUBECONFIG_PATH" -n "$NAMESPACE" get pods -o json >"$PODS_JSON"
else
    kubectl --kubeconfig "$KUBECONFIG_PATH" get pods -A -o json >"$PODS_JSON"
fi

python3 - "$PROFILE_FILE" "$PODS_JSON" <<'PY'
import json
import sys

profile_file, pods_json = sys.argv[1:3]
try:
    import yaml
except ImportError:
    yaml = None

profiles = {
    "defaults": {
        "request_cpu_m": 50,
        "request_memory_mib": 128,
        "limit_cpu_multiplier": 4,
        "limit_memory_multiplier": 2,
    },
    "namespaces": {},
}
if yaml:
    with open(profile_file, encoding="utf-8") as handle:
        loaded = yaml.safe_load(handle) or {}
        profiles["defaults"].update(loaded.get("defaults", {}))
        profiles["namespaces"].update(loaded.get("namespaces", {}))

with open(pods_json, encoding="utf-8") as handle:
    pods = json.load(handle).get("items", [])
seen = set()

def profile_for(namespace):
    profile = dict(profiles["defaults"])
    profile.update(profiles["namespaces"].get(namespace, {}))
    return profile

print("Jeannie Capacity Limits")
print("=======================")
print("mode: recommendations only")
print(f"profile_file: {profile_file}")

count = 0
for pod in pods:
    namespace = pod["metadata"].get("namespace", "default")
    owner = namespace
    for ref in pod["metadata"].get("ownerReferences", []):
        if ref.get("kind") in {"ReplicaSet", "StatefulSet", "DaemonSet", "Job"}:
            owner = ref.get("name", owner)
            break
    for container in pod.get("spec", {}).get("containers", []):
        resources = container.get("resources", {})
        requests = resources.get("requests", {})
        limits = resources.get("limits", {})
        if requests.get("cpu") and requests.get("memory") and limits.get("cpu") and limits.get("memory"):
            continue
        key = (namespace, owner, container["name"])
        if key in seen:
            continue
        seen.add(key)
        profile = profile_for(namespace)
        request_cpu = int(profile["request_cpu_m"])
        request_memory = int(profile["request_memory_mib"])
        limit_cpu = request_cpu * int(profile["limit_cpu_multiplier"])
        limit_memory = request_memory * int(profile["limit_memory_multiplier"])
        count += 1
        print(f"\n{count}. {namespace}/{owner}:{container['name']}")
        print("   Add or tune this resources block in the owning manifest/chart:")
        print("   resources:")
        print("     requests:")
        print(f"       cpu: {request_cpu}m")
        print(f"       memory: {request_memory}Mi")
        print("     limits:")
        print(f"       cpu: {limit_cpu}m")
        print(f"       memory: {limit_memory}Mi")

if count == 0:
    print("\nNo containers missing requests/limits were found.")
else:
    print("\nNotes:")
    print("- Treat these as starting values, not truth.")
    print("- Prefer app namespaces first; be careful with kube-system/control-plane pods.")
    print("- After changes, run ./jeannie resource-budget and ./jeannie capacity.")
PY
