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

HUB_URL="${SHELLFLEET_HUB:-https://agent.vnstech.cloud}"
GROUP="${SHELLFLEET_GROUP:-/}"
BUNDLE_URL="${SHELLFLEET_BUNDLE_URL:-https://filesv.vnstech.cloud/shell-fleet-20260603.tgz}"
WHEELHOUSE_URL="${SHELLFLEET_WHEELHOUSE_URL:-https://filesv.vnstech.cloud/shellfleet-agent-wheelhouse-py311-linux-x86_64.tgz}"
PROXY="${SHELLFLEET_PROXY:-}"
PROXY_SOURCE=""
AGENT_USER="${SHELLFLEET_AGENT_USER:-shellfleet-agent}"
PYTHON_BIN="${SHELLFLEET_PYTHON:-}"
detect_os_name() {
  if [ -r /etc/os-release ]; then
    . /etc/os-release
    case "${ID:-}:${ID_LIKE:-}" in
      *ubuntu*|*debian*) printf 'Linux'; return 0 ;;
      *) printf 'Linux'; return 0 ;;
    esac
  fi
  if [ -x /usr/bin/sw_vers ] || [ -d /System/Library/CoreServices ]; then
    printf 'Darwin'; return 0
  fi
  if command -v uname >/dev/null 2>&1; then
    uname -s; return 0
  fi
  printf 'Unknown'
}
OS_NAME="$(detect_os_name)"
KEEP_WORKDIR="${SHELLFLEET_KEEP_WORKDIR:-0}"
WORKDIR="$(mktemp -d 2>/dev/null || mktemp -d -t shellfleet)"

case "$OS_NAME" in
  Linux) PREFIX="${SHELLFLEET_PREFIX:-/opt/shellfleet-agent}"; SERVICE_MODE="systemd" ;;
  Darwin) PREFIX="${SHELLFLEET_PREFIX:-/Library/ShellFleetAgent}"; SERVICE_MODE="launchd" ;;
  *) echo "Error: unsupported OS: $OS_NAME" >&2; exit 1 ;;
esac

if [ -t 1 ]; then
  RESET='\033[0m'; BOLD='\033[1m'; DIM='\033[2m'
  CYAN='\033[36m'; GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; BLUE='\033[34m'
else
  RESET=''; BOLD=''; DIM=''; CYAN=''; GREEN=''; YELLOW=''; RED=''; BLUE=''
fi

cleanup() { [ "$KEEP_WORKDIR" = "1" ] || rm -rf "$WORKDIR"; }
trap cleanup EXIT
say() { printf '%b\n' "$*"; }
step() { say "${BLUE}${BOLD}==>${RESET} ${BOLD}$*${RESET}"; }
ok() { say "${GREEN}✓${RESET} $*"; }
warn() { say "${YELLOW}!${RESET} $*"; }
die() { say "${RED}✗ Error:${RESET} $*" >&2; exit 1; }

banner() {
  say "${CYAN}${BOLD}+----------------------------------------------------------+${RESET}"
  say "${CYAN}${BOLD}|              Shell Fleet Agent Installer                  |${RESET}"
  say "${CYAN}${BOLD}+----------------------------------------------------------+${RESET}"
  say "${DIM}  OS    : $OS_NAME${RESET}"
  say "${DIM}  Hub   : $HUB_URL${RESET}"
  say "${DIM}  Group : $GROUP${RESET}"
  say "${DIM}  Prefix: $PREFIX${RESET}"
  printf '\n'
}

need_root() {
  [ "$(id -u)" -eq 0 ] || die 'Run as root. Example: curl -fsSL https://filesv.vnstech.cloud/install_agent | sudo -E bash'
}
need_command() { command -v "$1" >/dev/null 2>&1 || die "missing required command: $1"; }

select_python() {
  if [ -n "$PYTHON_BIN" ]; then
    command -v "$PYTHON_BIN" >/dev/null 2>&1 || die "SHELLFLEET_PYTHON not found: $PYTHON_BIN"
    return 0
  fi
  for candidate in python3.11 python3; do
    if command -v "$candidate" >/dev/null 2>&1; then
      PYTHON_BIN="$candidate"
      return 0
    fi
  done
  die 'python3.11 or python3 is required'
}

python_venv_package_name() {
  version="$($PYTHON_BIN - <<'PYVER'
import sys
print(f"python{sys.version_info.major}.{sys.version_info.minor}-venv")
PYVER
)"
  printf '%s' "$version"
}

install_linux_deps() {
  missing=""
  command -v curl >/dev/null 2>&1 || missing="$missing curl"
  command -v tar >/dev/null 2>&1 || missing="$missing tar"
  command -v "$PYTHON_BIN" >/dev/null 2>&1 || missing="$missing $PYTHON_BIN"
  "$PYTHON_BIN" -m venv --help >/dev/null 2>&1 || missing="$missing $(python_venv_package_name)"
  if [ -n "$missing" ]; then
    command -v apt-get >/dev/null 2>&1 || die "missing packages:$missing, and apt-get not found"
    step "Installing missing packages:$missing"
    if apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y $missing; then
      ok 'Missing packages installed.'
    else
      warn 'apt/dpkg failed. Continuing with Python fallback where possible.'
      warn 'You should later repair dpkg manually, e.g. sudo dpkg --configure -a'
    fi
  else
    ok 'Required Linux packages are present.'
  fi
}

install_macos_deps() {
  need_command curl; need_command tar; need_command "$PYTHON_BIN"
  "$PYTHON_BIN" -m venv --help >/dev/null 2>&1 || die "$PYTHON_BIN venv is unavailable. Install Python 3.11 from python.org or Homebrew."
  ok 'Required macOS commands are present.'
}

set_proxy() {
  PROXY="$1"; PROXY_SOURCE="$2"; return 0
}

proxy_from_env() {
  for name in SHELLFLEET_PROXY HTTPS_PROXY https_proxy HTTP_PROXY http_proxy ALL_PROXY all_proxy; do
    value="${!name:-}"
    [ -n "$value" ] && set_proxy "$value" "env:$name" && return 0
  done
  return 1
}

proxy_from_apt_files() {
  for file in /etc/apt/apt.conf /etc/apt/apt.conf.d/* /etc/environment; do
    [ -r "$file" ] || continue
    value="$({
      sed -nE 's/^[[:space:]]*Acquire::(https?|HTTPS?)::Proxy[[:space:]]+"([^"]+)";.*/\2/p' "$file"
      sed -nE "s/^[[:space:]]*Acquire::(https?|HTTPS?)::Proxy[[:space:]]+'([^']+)';.*/\2/p" "$file"
      sed -nE 's/^[[:space:]]*(https?|HTTPS?)_proxy=("?)([^"[:space:]]+)\2.*/\3/p' "$file"
      sed -nE 's/^[[:space:]]*(HTTPS?|https?)_PROXY=("?)([^"[:space:]]+)\2.*/\3/p' "$file"
    } | grep -E '^https?://' | grep -vi 'DIRECT' | head -n 1 || true)"
    [ -n "$value" ] && set_proxy "$value" "apt:$file" && return 0
  done
  return 1
}

proxy_from_macos_scutil() {
  command -v scutil >/dev/null 2>&1 || return 1
  proxy_host="$(scutil --proxy | awk '/HTTPProxy/ {print $3; exit}')"
  proxy_port="$(scutil --proxy | awk '/HTTPPort/ {print $3; exit}')"
  proxy_enabled="$(scutil --proxy | awk '/HTTPEnable/ {print $3; exit}')"
  if [ "$proxy_enabled" = "1" ] && [ -n "$proxy_host" ] && [ -n "$proxy_port" ]; then
    set_proxy "http://${proxy_host}:${proxy_port}" 'macos:scutil HTTP'; return 0
  fi
  https_host="$(scutil --proxy | awk '/HTTPSProxy/ {print $3; exit}')"
  https_port="$(scutil --proxy | awk '/HTTPSPort/ {print $3; exit}')"
  https_enabled="$(scutil --proxy | awk '/HTTPSEnable/ {print $3; exit}')"
  if [ "$https_enabled" = "1" ] && [ -n "$https_host" ] && [ -n "$https_port" ]; then
    set_proxy "http://${https_host}:${https_port}" 'macos:scutil HTTPS'; return 0
  fi
  return 1
}

detect_proxy() {
  step 'Detecting outbound proxy'
  if [ -n "${SHELLFLEET_PROXY:-}" ]; then
    set_proxy "$SHELLFLEET_PROXY" 'env:SHELLFLEET_PROXY'
  elif [ "$OS_NAME" = "Linux" ]; then
    proxy_from_apt_files || proxy_from_env || true
  else
    proxy_from_env || proxy_from_macos_scutil || true
  fi
  if [ -n "$PROXY" ]; then ok "Using proxy from $PROXY_SOURCE: $PROXY"; else warn 'No proxy detected; using direct connection.'; fi
}

create_agent_user_linux() {
  if ! id "$AGENT_USER" >/dev/null 2>&1; then
    useradd --system --home "$PREFIX" --shell /usr/sbin/nologin "$AGENT_USER"
    ok "Created system user $AGENT_USER."
  fi
  install -d -m 0750 -o "$AGENT_USER" -g "$AGENT_USER" "$PREFIX"
}
create_prefix_macos() { install -d -m 0755 "$PREFIX"; }

install_python_agent() {
  step "Creating Python environment at $PREFIX/venv"
  if python3 -m venv "$PREFIX/venv"; then
    ok 'venv created with bundled pip.'
  else
    warn 'python3 -m venv failed, likely because ensurepip/python3-venv is missing.'
    warn 'Trying venv --without-pip and bootstrapping pip with get-pip.py.'
    rm -rf "$PREFIX/venv"
    "$PYTHON_BIN" -m venv --without-pip "$PREFIX/venv" || die 'cannot create venv even with --without-pip'
    curl "${CURL_ARGS[@]}" -o "$WORKDIR/get-pip.py" https://filesv.vnstech.cloud/get-pip.py
      "$PREFIX/venv/bin/python" "$WORKDIR/get-pip.py" --quiet --no-index --find-links "$WORKDIR/wheelhouse"
    ok 'pip bootstrapped inside venv.'
  fi
  export PYTHONDONTWRITEBYTECODE=1
  PIP_FLAGS=(--quiet --no-index --find-links "$WORKDIR/wheelhouse" --no-compile)
  "$PREFIX/venv/bin/python" -m pip install "${PIP_FLAGS[@]}" --upgrade pip setuptools wheel
  step 'Installing Shell Fleet agent packages'
  "$PREFIX/venv/bin/python" -m pip install "${PIP_FLAGS[@]}" "$BUNDLE_DIR/protocol" "$BUNDLE_DIR/agent"
  "$PREFIX/venv/bin/python" -m pip install "${PIP_FLAGS[@]}" psutil 2>/dev/null || true
  cat > "$PREFIX/start.sh" <<EOF_START
#!/usr/bin/env bash
export SHELLFLEET_CONFIG="$PREFIX/agent.json"
exec "$PREFIX/venv/bin/shellfleet-agent" run
EOF_START
  chmod 755 "$PREFIX/start.sh"
}

enroll_agent() {
  step "Enrolling agent to $HUB_URL"
  say "${DIM}Use an admin or agent-role Shell Fleet account.${RESET}"
  export SHELLFLEET_CONFIG="$PREFIX/agent.json"
  ENROLL_ARGS=(enroll --hub "$HUB_URL" --group "$GROUP")
  [ -z "$PROXY" ] || ENROLL_ARGS+=(--proxy "$PROXY")
  if [ -r /dev/tty ]; then
    "$PREFIX/venv/bin/shellfleet-agent" "${ENROLL_ARGS[@]}" </dev/tty
  else
    die 'No interactive terminal found for enrollment. Download the script first, then run it from a terminal with sudo.'
  fi
  chmod 600 "$PREFIX/agent.json"
}

install_systemd_service() {
  step 'Installing systemd service'
  chown -R "$AGENT_USER:$AGENT_USER" "$PREFIX"
  cat > /etc/systemd/system/shellfleet-agent.service <<EOF_SERVICE
[Unit]
Description=Shell Fleet Agent
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=$AGENT_USER
Group=$AGENT_USER
Environment=SHELLFLEET_CONFIG=$PREFIX/agent.json
WorkingDirectory=$PREFIX
ExecStart=$PREFIX/start.sh
Restart=always
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=$PREFIX

[Install]
WantedBy=multi-user.target
EOF_SERVICE
  systemctl daemon-reload
  systemctl enable --now shellfleet-agent
  sleep 2
  systemctl is-active --quiet shellfleet-agent || {
    journalctl -u shellfleet-agent --no-pager -n 40 >&2 || true
    die 'shellfleet-agent service did not start'
  }
  ok 'systemd service is running.'
}

install_launchd_service() {
  step 'Installing macOS LaunchDaemon'
  cat > /Library/LaunchDaemons/com.shellfleet.agent.plist <<EOF_PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
  <key>Label</key><string>com.shellfleet.agent</string>
  <key>ProgramArguments</key><array><string>$PREFIX/start.sh</string></array>
  <key>EnvironmentVariables</key><dict><key>SHELLFLEET_CONFIG</key><string>$PREFIX/agent.json</string></dict>
  <key>WorkingDirectory</key><string>$PREFIX</string>
  <key>RunAtLoad</key><true/><key>KeepAlive</key><true/>
  <key>StandardOutPath</key><string>/var/log/shellfleet-agent.log</string>
  <key>StandardErrorPath</key><string>/var/log/shellfleet-agent.log</string>
</dict></plist>
EOF_PLIST
  chown root:wheel /Library/LaunchDaemons/com.shellfleet.agent.plist
  chmod 644 /Library/LaunchDaemons/com.shellfleet.agent.plist
  launchctl bootout system /Library/LaunchDaemons/com.shellfleet.agent.plist >/dev/null 2>&1 || true
  launchctl bootstrap system /Library/LaunchDaemons/com.shellfleet.agent.plist
  launchctl enable system/com.shellfleet.agent
  sleep 2
  launchctl print system/com.shellfleet.agent >/dev/null || die 'launchd service did not start'
  ok 'LaunchDaemon is running.'
}

banner
need_root
select_python
ok "Using Python: $PYTHON_BIN ($($PYTHON_BIN --version 2>&1))"
case "$OS_NAME" in
  Linux) install_linux_deps; create_agent_user_linux ;;
  Darwin) install_macos_deps; create_prefix_macos ;;
esac

detect_proxy
CURL_ARGS=(-fsSL --retry 3 --connect-timeout 15)
[ -z "$PROXY" ] || CURL_ARGS+=(--proxy "$PROXY")
step 'Downloading Shell Fleet bundle'
curl "${CURL_ARGS[@]}" -o "$WORKDIR/shell-fleet.tgz" "$BUNDLE_URL"
tar -xzf "$WORKDIR/shell-fleet.tgz" -C "$WORKDIR"
step 'Downloading offline Python wheelhouse'
mkdir -p "$WORKDIR/wheelhouse"
curl "${CURL_ARGS[@]}" -o "$WORKDIR/wheelhouse.tgz" "$WHEELHOUSE_URL"
tar -xzf "$WORKDIR/wheelhouse.tgz" -C "$WORKDIR/wheelhouse"
BUNDLE_DIR="$(find "$WORKDIR" -maxdepth 2 -type f -name install.sh -print -quit | sed 's#/install.sh$##')"
[ -n "$BUNDLE_DIR" ] || die 'bundle is invalid: install.sh not found'
[ -d "$BUNDLE_DIR/protocol" ] || die 'bundle is invalid: protocol package not found'
[ -d "$BUNDLE_DIR/agent" ] || die 'bundle is invalid: agent package not found'
ok "Bundle downloaded and verified: $BUNDLE_DIR"
install_python_agent
enroll_agent
case "$SERVICE_MODE" in
  systemd) install_systemd_service ;;
  launchd) install_launchd_service ;;
esac

printf '\n'
say "${GREEN}${BOLD}Shell Fleet agent installed and running.${RESET}"
say "OS: $OS_NAME"
say "Hub: $HUB_URL"
say "Config: $PREFIX/agent.json"
case "$SERVICE_MODE" in
  systemd) say 'Status: systemctl status shellfleet-agent'; say 'Logs:   journalctl -u shellfleet-agent -f' ;;
  launchd) say 'Status: launchctl print system/com.shellfleet.agent'; say 'Logs:   tail -f /var/log/shellfleet-agent.log' ;;
esac
