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

usage() {
  cat <<'EOF'
PowerSearch Grid Edge Agent installer (MVP)

Installs a user-level systemd service:
  - files:   ~/.local/share/powersearch-grid-agent/
  - config:  ~/.config/powersearch-grid/agent.json
  - unit:    ~/.config/systemd/user/powersearch-grid-agent.service

Usage:
  bash install_edge_agent.sh --url https://aipowerprogressia.com
  bash install_edge_agent.sh --upgrade
  bash install_edge_agent.sh --re-register
  bash install_edge_agent.sh --print-plan
  bash install_edge_agent.sh --uninstall

Notes:
  - Safe to re-run: by default this script upgrades the agent without re-registering and preserves your policy.
  - Use --re-register if you need a new node_id/node_token (policy is preserved).
  - To move to a new control-plane URL, use: --url https://new-host --re-register

Optional env vars:
  GRID_REG_TOKEN=...          Registration token (if the server requires one)
  GRID_PROVIDER_TOKEN=...     Provider token (binds this node to your account for earnings)
  GRID_DISPLAY_NAME=...       Optional node display name (defaults to empty; avoids sharing hostname)
  GRID_PUBKEY_FPR_SHA256=...  Expected Grid public-key fingerprint (sha256) for signed manifest verification
  GRID_OLLAMA_MODEL=...       Ollama model name on this node (for ollama_chat jobs)
  GRID_OLLAMA_BASE_URL=...    Ollama base URL (default: http://127.0.0.1:11434)
  POWERSEARCH_GRID_URL=...    Same as --url
  PYTHON_BIN=python3          Override python binary
EOF
}

BASE_URL="${POWERSEARCH_GRID_URL:-}"
BASE_URL_EXPLICIT=0
if [ -n "${BASE_URL:-}" ]; then
  BASE_URL_EXPLICIT=1
fi
PYTHON_BIN="${PYTHON_BIN:-python3}"
PRINT_PLAN=0
DO_UNINSTALL=0
NO_SERVICE=0
UPGRADE_ONLY=0
RE_REGISTER=0

while [ $# -gt 0 ]; do
  case "$1" in
    --url)
      BASE_URL="${2:-}"; BASE_URL_EXPLICIT=1; shift 2 ;;
    --print-plan)
      PRINT_PLAN=1; shift 1 ;;
    --uninstall)
      DO_UNINSTALL=1; shift 1 ;;
    --upgrade|--upgrade-only)
      UPGRADE_ONLY=1; shift 1 ;;
    --re-register|--reregister|--force-register)
      RE_REGISTER=1; shift 1 ;;
    --no-service)
      NO_SERVICE=1; shift 1 ;;
    -h|--help)
      usage; exit 0 ;;
    *)
      echo "Unknown arg: $1" >&2
      usage
      exit 2 ;;
  esac
done

BASE_URL="${BASE_URL:-https://aipowerprogressia.com}"
BASE_URL="${BASE_URL%/}"
REG_TOKEN="${GRID_REG_TOKEN:-}"
PROVIDER_TOKEN="${GRID_PROVIDER_TOKEN:-}"
DISPLAY_NAME="${GRID_DISPLAY_NAME:-}"
OLLAMA_MODEL="${GRID_OLLAMA_MODEL:-}"
OLLAMA_BASE_URL="${GRID_OLLAMA_BASE_URL:-http://127.0.0.1:11434}"
OLLAMA_BASE_URL_EXPLICIT=0
if [ -n "${GRID_OLLAMA_BASE_URL:-}" ]; then
  OLLAMA_BASE_URL_EXPLICIT=1
fi

if ! command -v curl >/dev/null 2>&1; then
  echo "curl is required" >&2
  exit 1
fi
if ! command -v "$PYTHON_BIN" >/dev/null 2>&1; then
  echo "python3 is required" >&2
  exit 1
fi

AGENT_DIR="${HOME}/.local/share/powersearch-grid-agent"
CONF_DIR="${HOME}/.config/powersearch-grid"
UNIT_DIR="${HOME}/.config/systemd/user"
CFG_PATH="${CONF_DIR}/agent.json"
UNIT_PATH="${UNIT_DIR}/powersearch-grid-agent.service"

EXISTING_NODE_ID=""
EXISTING_NODE_TOKEN=""
EXISTING_BASE_URL=""
EXISTING_POLICY_JSON=""
EXISTING_OLLAMA_MODEL=""
EXISTING_OLLAMA_BASE_URL=""
EXISTING_PUBKEY_B64=""
HAVE_EXISTING_CONFIG=0

if [ -f "$CFG_PATH" ]; then
  while IFS=$'\t' read -r k v; do
    case "$k" in
      node_id) EXISTING_NODE_ID="$v" ;;
      node_token) EXISTING_NODE_TOKEN="$v" ;;
      base_url) EXISTING_BASE_URL="$v" ;;
      policy_json) EXISTING_POLICY_JSON="$v" ;;
      ollama_model) EXISTING_OLLAMA_MODEL="$v" ;;
      ollama_base_url) EXISTING_OLLAMA_BASE_URL="$v" ;;
      signing_public_key_b64) EXISTING_PUBKEY_B64="$v" ;;
    esac
  done < <(CFG_PATH="$CFG_PATH" "$PYTHON_BIN" - <<'PY'
import json, os
from pathlib import Path

p = Path(os.environ.get("CFG_PATH") or "")
try:
    d = json.loads(p.read_text(encoding="utf-8", errors="ignore"))
except Exception:
    d = {}

def out(k: str, v: object) -> None:
    if v is None:
        s = ""
    else:
        s = str(v)
    s = s.replace("\t", " ").replace("\n", " ").strip()
    print(k + "\t" + s)

out("node_id", d.get("node_id"))
out("node_token", d.get("node_token"))
out("base_url", d.get("base_url"))
pol = d.get("policy") if isinstance(d.get("policy"), dict) else None
out("policy_json", json.dumps(pol, separators=(",", ":"), ensure_ascii=False) if pol else "")
out("ollama_model", d.get("ollama_model"))
out("ollama_base_url", d.get("ollama_base_url"))
out("signing_public_key_b64", d.get("signing_public_key_b64"))
PY
  )
  if [ -n "${EXISTING_NODE_ID:-}" ] && [ -n "${EXISTING_NODE_TOKEN:-}" ]; then
    HAVE_EXISTING_CONFIG=1
  fi
fi

if [ "$BASE_URL_EXPLICIT" -eq 0 ] && [ -n "${EXISTING_BASE_URL:-}" ]; then
  BASE_URL="${EXISTING_BASE_URL%/}"
fi
if [ "$OLLAMA_BASE_URL_EXPLICIT" -eq 0 ] && [ -n "${EXISTING_OLLAMA_BASE_URL:-}" ]; then
  OLLAMA_BASE_URL="${EXISTING_OLLAMA_BASE_URL%/}"
fi

CPU_QUOTA="20%"
MEM_MAX="4G"
CPU_COUNT="$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1)"

compute_unit_caps() {
  read -r CPU_QUOTA MEM_MAX < <(CFG_PATH="$CFG_PATH" EXISTING_POLICY_JSON="$EXISTING_POLICY_JSON" CPU_COUNT="$CPU_COUNT" "$PYTHON_BIN" - <<'PY'
import json, os
from pathlib import Path

cpu_count = 1
try:
    cpu_count = int(os.environ.get("CPU_COUNT") or 1)
except Exception:
    cpu_count = 1
cpu_count = max(1, cpu_count)

policy = None
raw = (os.environ.get("EXISTING_POLICY_JSON") or "").strip()
if raw:
    try:
        policy = json.loads(raw)
    except Exception:
        policy = None

if not isinstance(policy, dict):
    p = Path(os.environ.get("CFG_PATH") or "")
    if p.exists():
        try:
            d = json.loads(p.read_text(encoding="utf-8", errors="ignore"))
        except Exception:
            d = {}
        pol = d.get("policy") if isinstance(d.get("policy"), dict) else None
        if isinstance(pol, dict):
            policy = pol

if not isinstance(policy, dict):
    policy = {}

try:
    cpu_max_percent = int(policy.get("cpu_max_percent", 20) or 20)
except Exception:
    cpu_max_percent = 20
cpu_max_percent = max(0, min(cpu_max_percent, 95))

try:
    ram_max_gb = int(policy.get("ram_max_gb", 4) or 4)
except Exception:
    ram_max_gb = 4
ram_max_gb = max(1, min(ram_max_gb, 512))

quota = max(5, min(int(cpu_max_percent * cpu_count), 2000))
print(f"{quota}% {ram_max_gb}G")
PY
)
  CPU_QUOTA="${CPU_QUOTA:-20%}"
  MEM_MAX="${MEM_MAX:-4G}"
}

compute_unit_caps || true

if [ "$PRINT_PLAN" -eq 1 ]; then
  cat <<EOF
Plan (no changes made):
  - download:  ${BASE_URL}/static/grid/* -> ${AGENT_DIR}/ (edge_agent.py + helpers + SHA256SUMS)
  - verify:    SHA256SUMS + signed release manifest (optional pinned key) when available
  - config:    ${CFG_PATH} $( [ "$HAVE_EXISTING_CONFIG" -eq 1 ] && [ "$RE_REGISTER" -eq 0 ] && echo "(reuse existing node_id ${EXISTING_NODE_ID})" || echo "(new registration)" )
  - unit:      ${UNIT_PATH} $( [ -f "$UNIT_PATH" ] && echo "(preserve if present)" || echo "" )
  - service:   $( [ "$NO_SERVICE" -eq 1 ] && echo "skip (--no-service)" || echo "systemctl --user enable --now (or restart if already installed)" )
  - caps:      CPUQuota=${CPU_QUOTA} · MemoryMax=${MEM_MAX} (Linux systemd --user only)

Notes:
  - resource sharing defaults to OFF (policy.enabled=false)
  - use GRID_REG_TOKEN=... if registration token is required
  - use --no-service if systemd --user is unavailable
  - use --upgrade to skip registration (requires existing config)
  - use --re-register to rotate node_id/node_token (preserves policy)
EOF
  exit 0
fi

if [ "$DO_UNINSTALL" -eq 1 ]; then
  if command -v systemctl >/dev/null 2>&1; then
    systemctl --user stop powersearch-grid-agent 2>/dev/null || true
    systemctl --user disable powersearch-grid-agent 2>/dev/null || true
    systemctl --user daemon-reload 2>/dev/null || true
  fi
  rm -f "$UNIT_PATH" || true
  rm -rf "$AGENT_DIR" || true
  rm -rf "$CONF_DIR" || true
  echo "Uninstalled PowerSearch Grid edge agent."
  exit 0
fi

if [ "$UPGRADE_ONLY" -eq 1 ] && [ "$HAVE_EXISTING_CONFIG" -ne 1 ]; then
  echo "[install] --upgrade requested but existing config was not found at: ${CFG_PATH}" >&2
  echo "[install] Run without --upgrade for first install, or use --re-register to create a new node." >&2
  exit 2
fi

mkdir -p "$AGENT_DIR" "$CONF_DIR" "$UNIT_DIR"

echo "[install] downloading Grid release assets..."
curl -fsSLo "${AGENT_DIR}/SHA256SUMS" "${BASE_URL}/static/grid/SHA256SUMS" || true

download_asset() {
  local name="$1"
  curl -fsSLo "${AGENT_DIR}/${name}" "${BASE_URL}/static/grid/${name}"
}

# Store a copy of the installer for offline review/verification in the agent dir.
# If the script is being piped to bash, fall back to downloading it.
SELF_PATH="${BASH_SOURCE[0]:-}"
if [ -f "${SELF_PATH:-}" ]; then
  cp -f "${SELF_PATH}" "${AGENT_DIR}/install_edge_agent.sh" 2>/dev/null || true
else
  download_asset "install_edge_agent.sh" 2>/dev/null || true
fi

download_asset "edge_agent.py"
download_asset "uninstall_edge_agent.sh" 2>/dev/null || true
download_asset "register_node.py" 2>/dev/null || true
download_asset "verify_grid_release.py" 2>/dev/null || true
download_asset "powersearch-grid-agent.plist" 2>/dev/null || true
download_asset "install_edge_agent_windows.ps1" 2>/dev/null || true
download_asset "uninstall_edge_agent_windows.ps1" 2>/dev/null || true

if command -v sha256sum >/dev/null 2>&1 && [ -s "${AGENT_DIR}/SHA256SUMS" ]; then
  echo "[install] verifying checksums via SHA256SUMS (best-effort)..."
  ( cd "${AGENT_DIR}" && for name in \
      edge_agent.py \
      install_edge_agent.sh \
      uninstall_edge_agent.sh \
      register_node.py \
      verify_grid_release.py \
      powersearch-grid-agent.plist \
      install_edge_agent_windows.ps1 \
      uninstall_edge_agent_windows.ps1 \
    ; do
      if [ -f "$name" ] && grep -q " ${name}$" SHA256SUMS 2>/dev/null; then
        grep " ${name}$" SHA256SUMS | sha256sum -c - >/dev/null
      fi
    done ) || {
      echo "[install] checksum verification failed; refusing to install" >&2
      exit 1
    }
else
  echo "[install] checksum tool/file unavailable; skipping SHA256SUMS verify" >&2
fi

AGENT_VERSION="$(
  AGENT_PATH="${AGENT_DIR}/edge_agent.py" "$PYTHON_BIN" - <<'PY'
import os, re
from pathlib import Path

path = Path(os.environ.get("AGENT_PATH") or "")
try:
    text = path.read_text(encoding="utf-8", errors="ignore")
except Exception:
    print("unknown")
    raise SystemExit(0)
m = re.search(r'(?m)^AGENT_VERSION\\s*=\\s*\"([^\"]+)\"\\s*$', text)
print((m.group(1) if m else "unknown").strip() or "unknown")
PY
)" || true
AGENT_VERSION="${AGENT_VERSION:-unknown}"

echo "[install] creating venv..."
if [ ! -x "${AGENT_DIR}/venv/bin/python" ]; then
  "$PYTHON_BIN" -m venv "${AGENT_DIR}/venv"
fi
"${AGENT_DIR}/venv/bin/pip" -q install -U pip wheel >/dev/null
"${AGENT_DIR}/venv/bin/pip" -q install "cryptography>=42.0.0" >/dev/null || {
  if [ -n "${GRID_PUBKEY_FPR_SHA256:-}" ]; then
    echo "[install] ERROR: failed to install cryptography but GRID_PUBKEY_FPR_SHA256 is set; cannot verify signed manifest" >&2
    exit 1
  fi
  echo "[install] note: failed to install cryptography; signed manifest verification may be unavailable (continuing with SHA256SUMS verification only)" >&2
}

echo "[install] verifying signed release manifest (best-effort)..."
PUBKEY_FPR_EXPECTED="${GRID_PUBKEY_FPR_SHA256:-}"
VERIFY_RC=0
VERIFY_OUT=""
PIN_ARGS=()
if [ -n "${PUBKEY_FPR_EXPECTED:-}" ]; then
  PIN_ARGS=(--pin-fingerprint-sha256 "${PUBKEY_FPR_EXPECTED}")
fi
if [ -f "${AGENT_DIR}/verify_grid_release.py" ]; then
  VERIFY_OUT="$("${AGENT_DIR}/venv/bin/python" "${AGENT_DIR}/verify_grid_release.py" --base-url "${BASE_URL}" "${PIN_ARGS[@]}" --verify-dir "${AGENT_DIR}" --require-all 2>&1)" || VERIFY_RC=$?
  if [ "$VERIFY_RC" -ne 0 ]; then
    if [ -n "${PUBKEY_FPR_EXPECTED:-}" ]; then
      echo "$VERIFY_OUT" >&2
      exit 1
    fi
    if echo "$VERIFY_OUT" | grep -Eiq "signed manifest unavailable|cryptography missing|network error|http [0-9]{3}"; then
      echo "[install] note: signed manifest verification unavailable; continuing with SHA256SUMS-only verification" >&2
    else
      echo "$VERIFY_OUT" >&2
      exit 1
    fi
  else
    echo "$VERIFY_OUT"
  fi
else
  echo "[install] verify_grid_release.py unavailable; skipping signed manifest verify" >&2
fi

NODE_ID=""
NODE_TOKEN=""
PUBKEY_B64=""

if [ "$HAVE_EXISTING_CONFIG" -eq 1 ] && [ "$RE_REGISTER" -eq 0 ]; then
  echo "[install] existing config found; skipping registration (use --re-register to rotate node identity)"
  NODE_ID="$EXISTING_NODE_ID"
  NODE_TOKEN="$EXISTING_NODE_TOKEN"
  PUBKEY_B64="$EXISTING_PUBKEY_B64"
else
  echo "[install] registering node with control-plane..."
  REG_JSON="$(BASE_URL="$BASE_URL" REG_TOKEN="$REG_TOKEN" PROVIDER_TOKEN="$PROVIDER_TOKEN" DISPLAY_NAME="$DISPLAY_NAME" AGENT_VERSION="$AGENT_VERSION" "$PYTHON_BIN" - <<'PY'
import json, os, platform, sys, urllib.request

base = (os.environ.get("BASE_URL") or "").rstrip("/")
reg_token = os.environ.get("REG_TOKEN") or ""
display_name = (os.environ.get("DISPLAY_NAME") or "").strip()[:120]
agent_version = (os.environ.get("AGENT_VERSION") or "unknown").strip()[:40] or "unknown"

payload = {
  "display_name": display_name,
  "platform": platform.platform(),
  "agent_version": agent_version,
  "consent": {"accepted": True, "accepted_utc": None},
  "policy": None,
}

data = json.dumps(payload).encode("utf-8")
headers = {"Content-Type": "application/json", "Accept": "application/json"}
if reg_token:
  headers["X-Grid-Registration-Token"] = reg_token
provider_token = os.environ.get("PROVIDER_TOKEN") or ""
if provider_token:
  headers["X-Grid-Provider-Token"] = provider_token

req = urllib.request.Request(base + "/api/grid/nodes/register", data=data, headers=headers, method="POST")
try:
  with urllib.request.urlopen(req, timeout=20) as resp:
    raw = resp.read().decode("utf-8")
except Exception as exc:
  print(json.dumps({"ok": False, "error": str(exc)}))
  sys.exit(0)
print(raw)
PY
)"

  NODE_ID="$("$PYTHON_BIN" - <<'PY' <<<"$REG_JSON"
import json, sys
try:
  d = json.load(sys.stdin)
except Exception:
  d = {}
if not d.get("ok"):
  raise SystemExit(1)
print(d.get("node_id",""))
PY
  )" || {
  echo "[install] registration failed. response:" >&2
  echo "$REG_JSON" >&2
  echo "[install] If the server requires a registration token, set GRID_REG_TOKEN=... and rerun." >&2
  exit 1
}

  NODE_TOKEN="$("$PYTHON_BIN" - <<'PY' <<<"$REG_JSON"
import json, sys
d = json.load(sys.stdin)
print(d.get("node_token",""))
PY
  )"

  PUBKEY_B64="$("$PYTHON_BIN" - <<'PY' <<<"$REG_JSON"
import json, sys
d = json.load(sys.stdin)
print(d.get("public_key_b64",""))
PY
  )"
fi

if [ -z "$NODE_ID" ] || [ -z "$NODE_TOKEN" ]; then
  echo "[install] registration returned empty node_id/token" >&2
  exit 1
fi

if [ "$HAVE_EXISTING_CONFIG" -ne 1 ] || [ "$RE_REGISTER" -eq 1 ]; then
  echo "[install] writing config: ${CFG_PATH}"
  CFG_PATH="$CFG_PATH" BASE_URL="$BASE_URL" NODE_ID="$NODE_ID" NODE_TOKEN="$NODE_TOKEN" PUBKEY_B64="$PUBKEY_B64" \
    PUBKEY_FPR_EXPECTED="$PUBKEY_FPR_EXPECTED" \
    OLLAMA_MODEL="$OLLAMA_MODEL" OLLAMA_BASE_URL="$OLLAMA_BASE_URL" EXISTING_POLICY_JSON="$EXISTING_POLICY_JSON" \
    EXISTING_OLLAMA_MODEL="$EXISTING_OLLAMA_MODEL" EXISTING_OLLAMA_BASE_URL="$EXISTING_OLLAMA_BASE_URL" \
    "$PYTHON_BIN" - <<PY
import base64, hashlib, json, os, sys
from urllib.parse import urlparse

cfg_path = os.environ["CFG_PATH"]
base_url = os.environ["BASE_URL"].rstrip("/")
node_id = os.environ["NODE_ID"]
node_token = os.environ["NODE_TOKEN"]
pubkey = os.environ.get("PUBKEY_B64","").strip()
expected_fpr = (os.environ.get("PUBKEY_FPR_EXPECTED") or "").strip().lower()
ollama_model = (os.environ.get("OLLAMA_MODEL") or "").strip()
ollama_base_url = (os.environ.get("OLLAMA_BASE_URL") or "http://127.0.0.1:11434").strip().rstrip("/")

base_host = ""
try:
  base_host = (urlparse(base_url).hostname or "").strip().lower()
except Exception:
  base_host = ""

pub_fpr = ""
if pubkey:
  try:
    raw = base64.b64decode(pubkey.encode("utf-8"), validate=True)
    pub_fpr = hashlib.sha256(raw).hexdigest()
  except Exception:
    pub_fpr = ""
if expected_fpr and (not pub_fpr or pub_fpr != expected_fpr):
  print("[install] ERROR: signing public-key fingerprint mismatch (pinned key)", file=sys.stderr)
  print(f"expected: {expected_fpr or '(empty)'}", file=sys.stderr)
  print(f"actual:   {pub_fpr or '(unavailable)'}", file=sys.stderr)
  raise SystemExit(1)

policy = None
try:
  raw = (os.environ.get("EXISTING_POLICY_JSON") or "").strip()
  if raw:
    policy = json.loads(raw)
except Exception:
  policy = None
if not isinstance(policy, dict):
  policy = {
    "enabled": False,
    "cpu_max_percent": 20,
    "ram_max_gb": 4,
    "gpu_max_percent": 15,
    "disk_max_gb": 50,
    "disk_min_free_gb": 2,
    "network_upload_mbps": 3,
    "network_download_mbps": 10,
    "idle_only": True,
    "plugged_in_only": False,
    "quiet_hours": ["08:00-18:00"],
    "allowed_job_types": ["health_check", "crawl_url", "ollama_chat"],
    "crawl_allowlist_domains": [base_host] if base_host else [],
    "allow_private_crawl_ips": False,
    "crawl_max_redirects": 3,
    "max_concurrent_jobs": 1,
    "reserve_cores_for_user": 2,
    "reserve_ram_gb_for_user": 4,
    "thermal_throttle_enabled": True,
    "emergency_stop_enabled": True,
    "local_user_priority": True,
  }

if not ollama_model:
  ollama_model = (os.environ.get("EXISTING_OLLAMA_MODEL") or "").strip()
if not ollama_base_url:
  ollama_base_url = (os.environ.get("EXISTING_OLLAMA_BASE_URL") or "").strip().rstrip("/") or "http://127.0.0.1:11434"

cfg = {
  "base_url": base_url,
  "node_id": node_id,
  "node_token": node_token,
  "signing_public_key_b64": pubkey,
  "signing_public_key_fingerprint_sha256": pub_fpr,
  "ollama_base_url": ollama_base_url,
  "ollama_model": ollama_model,
  "policy": policy,
}
if expected_fpr:
  cfg["signing_public_key_fingerprint_sha256_expected"] = expected_fpr

os.makedirs(os.path.dirname(cfg_path), exist_ok=True)
with open(cfg_path, "w", encoding="utf-8") as f:
  json.dump(cfg, f, ensure_ascii=False, indent=2, sort_keys=True)
  f.write("\n")
PY

  chmod 600 "$CFG_PATH" || true
fi

compute_unit_caps || true

if [ "$NO_SERVICE" -eq 0 ]; then
  UNIT_MARKER="Generated by PowerSearch Grid installer"
  UNIT_MANAGED=0
  if [ -f "$UNIT_PATH" ] && grep -q "$UNIT_MARKER" "$UNIT_PATH" 2>/dev/null; then
    UNIT_MANAGED=1
  elif [ -f "$UNIT_PATH" ] && grep -q "powersearch-grid-agent/edge_agent.py --config %h/.config/powersearch-grid/agent.json" "$UNIT_PATH" 2>/dev/null; then
    # Back-compat: treat older generated units as managed (safe to update caps + paths).
    UNIT_MANAGED=1
  fi
  if [ ! -f "$UNIT_PATH" ] || [ "$UNIT_MANAGED" -eq 1 ]; then
    if [ -f "$UNIT_PATH" ]; then
      echo "[install] updating systemd unit: ${UNIT_PATH}"
    else
      echo "[install] writing systemd unit: ${UNIT_PATH}"
    fi
    cat >"$UNIT_PATH" <<EOF
# ${UNIT_MARKER}. Safe to overwrite on upgrade.
[Unit]
Description=PowerSearch Grid Edge Agent
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=%h/.local/share/powersearch-grid-agent
Environment=PYTHONUNBUFFERED=1
ExecStart=%h/.local/share/powersearch-grid-agent/venv/bin/python %h/.local/share/powersearch-grid-agent/edge_agent.py --config %h/.config/powersearch-grid/agent.json
Restart=always
RestartSec=5
Nice=10
IOSchedulingClass=idle
CPUAccounting=yes
MemoryAccounting=yes
CPUQuota=${CPU_QUOTA}
MemoryMax=${MEM_MAX}

[Install]
WantedBy=default.target
EOF
  else
    echo "[install] preserving existing systemd unit: ${UNIT_PATH}"
  fi
fi

if [ "$NO_SERVICE" -eq 0 ] && command -v systemctl >/dev/null 2>&1; then
  if systemctl --user daemon-reload 2>/dev/null; then
    if systemctl --user is-enabled powersearch-grid-agent >/dev/null 2>&1; then
      systemctl --user restart powersearch-grid-agent >/dev/null || true
      echo "[install] service restarted: systemctl --user status powersearch-grid-agent"
    else
      systemctl --user enable --now powersearch-grid-agent >/dev/null || true
      echo "[install] service started: systemctl --user status powersearch-grid-agent"
    fi
  else
    echo "[install] systemctl --user not available in this session. To start:" >&2
    echo "  systemctl --user daemon-reload" >&2
    echo "  systemctl --user enable --now powersearch-grid-agent" >&2
  fi
elif [ "$NO_SERVICE" -eq 1 ]; then
  echo "[install] --no-service requested; skipping systemd unit."
  echo "[install] Run the agent in the foreground with:"
  echo "  ${AGENT_DIR}/venv/bin/python ${AGENT_DIR}/edge_agent.py --config ${CFG_PATH}"
fi

echo
echo "[install] node_id: ${NODE_ID}"
echo "[install] config: ${CFG_PATH}"
if [ "$NO_SERVICE" -eq 0 ]; then
  echo "[install] caps (Linux systemd --user): CPUQuota=${CPU_QUOTA} MemoryMax=${MEM_MAX}"
fi
echo
echo "Next:"
echo "  1) Edit policy and set enabled=true:"
echo "     nano ~/.config/powersearch-grid/agent.json"
if [ "$NO_SERVICE" -eq 0 ]; then
  echo "  2) Restart the agent:"
  echo "     systemctl --user restart powersearch-grid-agent"
else
  echo "  2) Re-run the agent:"
  echo "     ${AGENT_DIR}/venv/bin/python ${AGENT_DIR}/edge_agent.py --config ${CFG_PATH}"
fi
