#!/bin/sh
set -eu

RAW_BASE_URL="${PRIVCLOUD_BASE_URL:-https://share.privcloud.fr}"
APP_DIR="$HOME/.local/share/privcloud-companion"
BIN_DIR="$HOME/.local/bin"
BIN_PATH="$BIN_DIR/privcloud-companion"
DESKTOP_DIR="$HOME/.config/autostart"
DESKTOP_FILE="$DESKTOP_DIR/privcloud-companion.desktop"
SYSTEMD_DIR="$HOME/.config/systemd/user"
SERVICE_FILE="$SYSTEMD_DIR/privcloud-companion.service"
STATE_DIR="$HOME/.privcloud-bridge"

if ! command -v node >/dev/null 2>&1; then
  echo "Node.js 20 or newer is required for this development installer." >&2
  echo "Production releases should use the signed bundled package." >&2
  exit 1
fi

NODE_BIN="$(command -v node)"
case "$NODE_BIN" in
  /*) ;;
  *)
    echo "Node.js must resolve to an absolute executable path." >&2
    exit 1
    ;;
esac
case "$NODE_BIN" in
  *[!A-Za-z0-9_./:+-]*)
    echo "Node.js resolved to an unsupported executable path." >&2
    exit 1
    ;;
esac
if ! "$NODE_BIN" -e 'process.exit(Number(process.versions.node.split(".")[0]) >= 20 ? 0 : 1)' \
  >/dev/null 2>&1
then
  echo "Node.js 20 or newer is required (found $(NODE_OPTIONS= "$NODE_BIN" --version))." >&2
  exit 1
fi

BASE_URL="$(NODE_OPTIONS= "$NODE_BIN" - "$RAW_BASE_URL" <<'NODE'
const raw = process.argv[2];
let url;
try {
  url = new URL(raw);
} catch {
  console.error("PRIVCLOUD_BASE_URL is not a valid absolute URL.");
  process.exit(1);
}
const loopback = ["localhost", "127.0.0.1", "::1"].includes(url.hostname);
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) {
  console.error("Use HTTPS (HTTP is accepted only for loopback development).");
  process.exit(1);
}
if (url.username || url.password || url.pathname !== "/" || url.search || url.hash) {
  console.error("PRIVCLOUD_BASE_URL must be an origin without credentials, path, query or fragment.");
  process.exit(1);
}
process.stdout.write(url.origin);
NODE
)"

SOURCE_TMP="$APP_DIR/privcloud-companion.tmp.mjs"
mkdir -p "$APP_DIR" "$BIN_DIR" "$DESKTOP_DIR" "$SYSTEMD_DIR" "$STATE_DIR"
chmod 0700 "$STATE_DIR"
trap 'rm -f "$SOURCE_TMP"' EXIT HUP INT TERM

curl -fsSL "$BASE_URL/install/companion/privcloud-companion.mjs" \
  -o "$SOURCE_TMP"
NODE_OPTIONS= "$NODE_BIN" --check "$SOURCE_TMP"
chmod 0755 "$SOURCE_TMP"
mv "$SOURCE_TMP" "$APP_DIR/privcloud-companion.mjs"

cat > "$BIN_PATH" <<EOF
#!/bin/sh
export PRIVCLOUD_BRIDGE_ORIGINS='$BASE_URL'
export PRIVCLOUD_COMPANION_NATIVE_ORIGINS='$BASE_URL'
exec '$NODE_BIN' '$APP_DIR/privcloud-companion.mjs' "\$@"
EOF
chmod 0755 "$BIN_PATH"

cat > "$DESKTOP_FILE" <<EOF
[Desktop Entry]
Type=Application
Name=PrivCloud Companion
Exec=$BIN_PATH
Terminal=false
X-GNOME-Autostart-enabled=true
EOF
chmod 0644 "$DESKTOP_FILE"

cat > "$SERVICE_FILE" <<EOF
[Unit]
Description=PrivCloud Companion local bridge
After=network-online.target

[Service]
Type=simple
ExecStart=$BIN_PATH
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=$STATE_DIR
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6

[Install]
WantedBy=default.target
EOF
chmod 0644 "$SERVICE_FILE"

curl -fsSL "$BASE_URL/install/companion/install/linux/register-native-messaging.sh" \
  -o "$APP_DIR/register-native-messaging.sh"
chmod 0755 "$APP_DIR/register-native-messaging.sh"
PRIVCLOUD_COMPANION_PATH="$BIN_PATH" "$APP_DIR/register-native-messaging.sh"

if command -v pkill >/dev/null 2>&1; then
  pkill -f "$APP_DIR/privcloud-companion.mjs" >/dev/null 2>&1 || true
fi

if command -v systemctl >/dev/null 2>&1 && \
  systemctl --user daemon-reload >/dev/null 2>&1; then
  # The supervised user service replaces the desktop autostart entry. Keeping
  # both enabled would launch a second process that can only fail on port 47631.
  cat > "$DESKTOP_FILE" <<EOF
[Desktop Entry]
Type=Application
Name=PrivCloud Companion
Exec=$BIN_PATH
Terminal=false
X-GNOME-Autostart-enabled=false
Hidden=true
EOF
  chmod 0644 "$DESKTOP_FILE"
  systemctl --user enable privcloud-companion.service
  systemctl --user restart privcloud-companion.service
else
  if command -v nohup >/dev/null 2>&1; then
    nohup "$BIN_PATH" >/dev/null 2>&1 &
  fi
fi

echo "PrivCloud Companion installed for the current user."
echo "If port 47631 is still served by an older development process, stop it and run: $BIN_PATH"
