#!/bin/bash
#
# stage_strongswan.sh — copy the monolithic strongSwan build into the app bundle,
# rewrite its install names to @rpath so it is relocatable, bundle openssl's
# libcrypto, code-sign every Mach-O with our Developer ID (so library validation
# is satisfied by same-team), and re-point the helper at the bundled libvici.
#
# Run as an app build phase (after the helper is embedded, before the final
# CodeSign). Expects src/strongswan-install/ from build_strongswan.sh.
#
# Usage: stage_strongswan.sh <path-to-SwanDesk.app>

set -euo pipefail

APP="${1:?usage: stage_strongswan.sh <SwanDesk.app>}"
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
INSTALL="$ROOT/src/strongswan-install"
INSTALL_LIB="$INSTALL/lib/ipsec"
# libcrypto is statically linked into libstrongswan (no separate libcrypto dylib).

SIGN_ID="${EXPANDED_CODE_SIGN_IDENTITY:-${SIGN_IDENTITY:-Developer ID Application: Juvex Oy (CXJY846WKU)}}"
HELPER="$APP/Contents/Library/LaunchServices/fi.juvex.swandeskhelper"

# A secure timestamp needs the network and is only required for notarization;
# skip it for Debug so local builds work offline.
TS=()
if [ "${CONFIGURATION:-Debug}" = "Release" ]; then TS=(--timestamp); fi

if [ ! -d "$INSTALL_LIB" ]; then
  echo "error: $INSTALL not found — run 'make strongswan' (Scripts/build_strongswan.sh) first" >&2
  exit 1
fi

DEST="$APP/Contents/Resources/strongswan"
echo "==> Staging strongSwan into $DEST"
rm -rf "$DEST"
mkdir -p "$DEST/lib/ipsec" "$DEST/libexec/ipsec" "$DEST/sbin" "$DEST/etc"

DYLIBS=(libstrongswan.0.dylib libcharon.0.dylib libtls.0.dylib libvici.0.dylib)

for lib in "${DYLIBS[@]}"; do cp "$INSTALL_LIB/$lib" "$DEST/lib/ipsec/"; done
cp "$INSTALL/libexec/ipsec/charon" "$DEST/libexec/ipsec/"
cp "$INSTALL/sbin/swanctl" "$DEST/sbin/"
cp -R "$INSTALL/etc/strongswan.conf" "$INSTALL/etc/strongswan.d" "$DEST/etc/"
chmod -R u+w "$DEST"

# Strip existing signatures before relocating. install_name_tool would otherwise
# warn that it invalidates an ad-hoc signature; we re-sign everything at the end.
for lib in "${DYLIBS[@]}"; do codesign --remove-signature "$DEST/lib/ipsec/$lib" 2>/dev/null || true; done
codesign --remove-signature "$DEST/libexec/ipsec/charon" 2>/dev/null || true
codesign --remove-signature "$DEST/sbin/swanctl" 2>/dev/null || true

# Rewrite every reference to the build-tree libs to @rpath form.
relocate_refs() {
  local f="$1"
  local lib
  for lib in "${DYLIBS[@]}"; do
    install_name_tool -change "$INSTALL_LIB/$lib" "@rpath/$lib" "$f" 2>/dev/null || true
  done
}

echo "==> Rewriting install names"
for lib in "${DYLIBS[@]}"; do
  f="$DEST/lib/ipsec/$lib"
  install_name_tool -id "@rpath/$lib" "$f"
  relocate_refs "$f"
  install_name_tool -add_rpath "@loader_path" "$f" 2>/dev/null || true   # siblings in lib/ipsec
done

relocate_refs "$DEST/libexec/ipsec/charon"
install_name_tool -add_rpath "@loader_path/../../lib/ipsec" "$DEST/libexec/ipsec/charon"

relocate_refs "$DEST/sbin/swanctl"
install_name_tool -add_rpath "@loader_path/../lib/ipsec" "$DEST/sbin/swanctl"

# Re-point the helper (built against the build-tree libvici) at the bundled copy.
# The helper lives in Contents/Library/LaunchServices; the libs are in
# Contents/Resources/strongswan/lib/ipsec.
echo "==> Re-pointing helper at bundled libvici"
install_name_tool -change "$INSTALL_LIB/libvici.0.dylib" "@rpath/libvici.0.dylib" "$HELPER" 2>/dev/null || true
install_name_tool -add_rpath "@executable_path/../../Resources/strongswan/lib/ipsec" "$HELPER" 2>/dev/null || true

echo "==> Verifying no build-tree / Homebrew paths remain"
if otool -L "$DEST/libexec/ipsec/charon" "$DEST/sbin/swanctl" "$DEST/lib/ipsec/"*.dylib "$HELPER" \
     | grep -E "$ROOT/src|/opt/homebrew" ; then
  echo "error: unrelocated absolute paths remain (see above)" >&2
  exit 1
fi

echo "==> Code-signing (inner-first) with: $SIGN_ID"
# Hardened runtime, no entitlements: every Mach-O here is signed with our team, so
# library validation is satisfied without disabling it. Dylibs first (dependencies),
# then the executables, then the re-pointed helper.
for lib in libstrongswan.0.dylib libtls.0.dylib libcharon.0.dylib libvici.0.dylib; do
  codesign --force --options runtime ${TS[@]+"${TS[@]}"} --sign "$SIGN_ID" "$DEST/lib/ipsec/$lib"
done
codesign --force --options runtime ${TS[@]+"${TS[@]}"} --sign "$SIGN_ID" "$DEST/libexec/ipsec/charon"
codesign --force --options runtime ${TS[@]+"${TS[@]}"} --sign "$SIGN_ID" "$DEST/sbin/swanctl"
codesign --force --options runtime ${TS[@]+"${TS[@]}"} --sign "$SIGN_ID" "$HELPER"

echo "==> strongSwan staged and signed."
