#!/bin/bash
# Build the audio daemon as a proper .app BUNDLE so it has a stable TCC identity.
#
# Why a bundle: a microphone grant is tied to the requesting program's identity.
# A bare launchd-spawned binary can't display a permission prompt (background
# context) and, with no bundle identity, gets silently denied. As a bundle with a
# stable CFBundleIdentifier (koi.skykoi.capture), we can grant the mic ONCE
# from a foreground `open`, and every later launchd spawn of the same bundle
# executable is recognized as that already-granted identity.
set -e
cd "$(dirname "$0")"
PLIST="$PWD/Info.plist"
# Codesign cert CN created by setup-codesign.sh — must match the keychain
# identity exactly (historical name; NOT the bundle id).
IDENT="SkyKoi Audio Daemon"
BUNDLE_ID="koi.skykoi.capture"
APP="$PWD/SkyKoiCapture.app"
rm -rf "$PWD/SkyKoiAudioDaemon.app"   # remove the old placeholder bundle name
EXE="$APP/Contents/MacOS/audio-daemon"
KC="$HOME/.skykoi/codesign/skykoi-codesign.keychain-db"

# 1. compile (also embed the plist in the bare exe as belt-and-suspenders).
# CRITICAL: pin an OLD deployment target. Without -target, swiftc uses the BUILD
# machine's OS as minos, so a daemon built on macOS 26 got minos 26.0 and linked
# macOS-26-only runtime dylibs (libswift_DarwinFoundation3) — it then dyld-aborts
# on every older Mac (the shipped binary never ran on macOS < 26). Target 13.0 so
# the binary runs on macOS 13+, and build UNIVERSAL so Intel Macs work too.
# SKYKOI_DAEMON_TARGET_OS overrides the minimum if ever needed.
TARGET_OS="${SKYKOI_DAEMON_TARGET_OS:-13.0}"
FRAMEWORKS="-framework AVFoundation -framework ScreenCaptureKit -framework CoreMedia"
LINKPLIST="-Xlinker -sectcreate -Xlinker __TEXT -Xlinker __info_plist -Xlinker $PLIST"
swiftc -O -target "arm64-apple-macos${TARGET_OS}" -o /tmp/audio-daemon.arm64 main.swift $FRAMEWORKS $LINKPLIST
if swiftc -O -target "x86_64-apple-macos${TARGET_OS}" -o /tmp/audio-daemon.x86_64 main.swift $FRAMEWORKS $LINKPLIST 2>/dev/null; then
  lipo -create /tmp/audio-daemon.arm64 /tmp/audio-daemon.x86_64 -output /tmp/audio-daemon.build
  rm -f /tmp/audio-daemon.arm64 /tmp/audio-daemon.x86_64
  echo "build: universal (arm64 + x86_64), min macOS ${TARGET_OS}"
else
  mv /tmp/audio-daemon.arm64 /tmp/audio-daemon.build
  echo "build: arm64 only (x86_64 cross-compile unavailable), min macOS ${TARGET_OS}"
fi

# 2. assemble the bundle (canonical home of the daemon)
rm -rf "$APP"
mkdir -p "$APP/Contents/MacOS"
cp "$PLIST" "$APP/Contents/Info.plist"
mv /tmp/audio-daemon.build "$EXE"
chmod +x "$EXE"
# back-compat symlink so anything referencing ./audio-daemon still resolves
ln -sf "SkyKoiCapture.app/Contents/MacOS/audio-daemon" "$PWD/audio-daemon"

# 3. sign the bundle — stable self-signed identity if trusted, else ad-hoc
[ -f "$KC" ] && security unlock-keychain -p skykoi-codesign "$KC" 2>/dev/null || true
if security find-identity -v -p codesigning 2>/dev/null | grep -q "$IDENT"; then
  # NOTE: deliberately NO --options runtime. Hardened runtime requires an explicit
  # com.apple.security.device.audio-input entitlement to use the mic; without it the
  # request is blocked and no consent dialog appears. We don't need hardened runtime
  # (no notarization), and the durable grant comes from the trusted cert identity.
  codesign --force --deep --sign "$IDENT" --identifier "$BUNDLE_ID" "$APP"
  echo "build: bundle signed with stable identity '$IDENT' (grant survives rebuilds) ✓"
else
  codesign --force --deep --sign - --identifier "$BUNDLE_ID" "$APP"
  echo "build: bundle ad-hoc signed (stable id $BUNDLE_ID) — mic grant holds until next rebuild"
fi
codesign -dv "$APP" 2>&1 | grep -iE "Identifier|Signature" | sed 's/^/  /'
echo "build: daemon at $EXE"
