#!/bin/sh
set -eu

ACTION=${1:-install}
SOURCE=/rootfs/usr/libexec/networkserviceproxy
MIRROR=/.sysroot/usr/libexec/networkserviceproxy
LEGACY_PATCHER=${MIRROR}.roothidepatch
STATE_DIR=/var/lib/relayrace
OWNED_FILE=$STATE_DIR/mirror-owned
ORIGINAL_STATE_FILE=$STATE_DIR/original-state
TARGET_FILE=$STATE_DIR/original-symlink-target
SESSION_FILE=$STATE_DIR/prepared-jbroot
RESET_SESSION_FILE=$STATE_DIR/reset-jbroot
RESET_TOOL=/usr/libexec/relayrace-reset-helper
NETWORKSERVICEPROXY_ENTITLEMENTS=/usr/lib/relayrace-roothide/networkserviceproxy.extra
LOCK_DIR=/var/run/relayrace-prepare.lock
LEGACY_MODE=/usr/lib/relayrace-roothide/mirror-mode
LEGACY_TARGET=/usr/lib/relayrace-roothide/original-symlink-target
TMP=

log() { printf '[RelayRace RootHide] %s\n' "$*"; }
fail() { printf '[RelayRace RootHide] ERROR: %s\n' "$*" >&2; exit 1; }

cleanup() {
    [ -z "${TMP:-}" ] || rm -f "$TMP" 2>/dev/null || true
    rmdir "$LOCK_DIR" 2>/dev/null || true
}
trap cleanup EXIT HUP INT TERM

if ! mkdir "$LOCK_DIR" 2>/dev/null; then
    log "prepare already running; skipping duplicate invocation."
    exit 0
fi

JBROOT_TOOL=$(command -v jbroot 2>/dev/null || true)
[ -n "$JBROOT_TOOL" ] || fail "RootHide jbroot tool is missing."
[ -x "$JBROOT_TOOL" ] || fail "RootHide jbroot tool is not executable."

jb_real() {
    "$JBROOT_TOOL" "$1"
}

resolve_roothide_tool() {
    logical="$1"

    # Some RootHide sessions expose /basebin directly, while others require
    # resolving it through the randomized current jbroot. Prefer whichever
    # executable actually exists instead of assuming one layout.
    if [ -x "$logical" ]; then
        printf '%s\n' "$logical"
        return 0
    fi

    resolved=$(jb_real "$logical" 2>/dev/null || true)
    if [ -n "$resolved" ] && [ -x "$resolved" ]; then
        printf '%s\n' "$resolved"
        return 0
    fi

    name=${logical##*/}
    found=$(command -v "$name" 2>/dev/null || true)
    if [ -n "$found" ] && [ -x "$found" ]; then
        printf '%s\n' "$found"
        return 0
    fi

    return 1
}

LDID=$(resolve_roothide_tool /basebin/ldid || true)
FAST_PATH_SIGN=$(resolve_roothide_tool /basebin/fastPathSign || true)
JBCTL=
if [ -z "$FAST_PATH_SIGN" ]; then
    # Dopamine RootHide 2.x/3.x supplies jbctl's trustcache command instead
    # of the Bootstrap fastPathSign executable.
    JBCTL=$(resolve_roothide_tool /basebin/jbctl || true)
fi

[ -f "$SOURCE" ] || fail "Stock networkserviceproxy is missing: $SOURCE"
[ -n "$LDID" ] || fail "RootHide ldid is missing (checked direct path, current jbroot, and PATH)."
[ -n "$FAST_PATH_SIGN" ] || [ -n "$JBCTL" ] || \
    fail "RootHide signing helper is missing: neither fastPathSign nor jbctl is executable (checked direct path, current jbroot, and PATH)."
[ -f "$NETWORKSERVICEPROXY_ENTITLEMENTS" ] || fail "RelayRace networkserviceproxy entitlement profile is missing."
[ -x "$RESET_TOOL" ] || fail "RelayRace reset helper is missing: $RESET_TOOL"

mkdir -p "$STATE_DIR" "$(dirname "$MIRROR")"

# Migrate state from the earlier experimental PatchLoader builds.
if [ ! -f "$OWNED_FILE" ] && [ -f "$LEGACY_MODE" ]; then
    legacy_mode=$(cat "$LEGACY_MODE" 2>/dev/null || true)
    case "$legacy_mode" in
        replaced-symlink|created)
            printf '%s\n' yes > "$OWNED_FILE"
            ;;
    esac
fi
if [ ! -f "$TARGET_FILE" ] && [ -f "$LEGACY_TARGET" ]; then
    cp -p "$LEGACY_TARGET" "$TARGET_FILE" 2>/dev/null || true
fi
rm -f "$LEGACY_MODE" "$LEGACY_TARGET" 2>/dev/null || true

# v18 did not explicitly record whether the original RootHide mirror entry was
# a symlink or absent.  Its target file exists only when there was a symlink,
# so upgrades can recover that state without touching the working mirror.
if [ -f "$OWNED_FILE" ] && [ ! -f "$ORIGINAL_STATE_FILE" ]; then
    if [ -s "$TARGET_FILE" ]; then
        printf '%s\n' symlink > "$ORIGINAL_STATE_FILE"
    else
        printf '%s\n' absent > "$ORIGINAL_STATE_FILE"
    fi
fi

CURRENT_JBROOT=$(jb_real /)
[ -n "$CURRENT_JBROOT" ] || fail "Could not resolve the current RootHide jbroot."

# Only reuse a same-session mirror if the full daemon profile is still valid.
# A partial preparation (for example, a failed reset) must not skip rebuilding
# a mirror whose stock entitlement was lost or whose old persona key returned.
signed_mirror_is_valid() {
    real_mirror=$(jb_real "$1" 2>/dev/null || true)
    [ -n "$real_mirror" ] || return 1
    signed_entitlements=$("$LDID" -e "$real_mirror" 2>/dev/null || true)
    printf '%s\n' "$signed_entitlements" | grep -q '<key>com.apple.private.security.no-sandbox</key>' || return 1
    printf '%s\n' "$signed_entitlements" | grep -q '<key>com.apple.networkd_privileged</key>' || return 1
    if printf '%s\n' "$signed_entitlements" | grep -q '<key>com.apple.private.persona-mgmt</key>'; then
        return 1
    fi
}

if [ -L "$MIRROR" ]; then
    target=$(readlink "$MIRROR" 2>/dev/null || true)
    [ -n "$target" ] || fail "Could not read RootHide's networkserviceproxy symlink."
    if [ ! -f "$OWNED_FILE" ]; then
        printf '%s\n' symlink > "$ORIGINAL_STATE_FILE"
        printf '%s\n' "$target" > "$TARGET_FILE"
        printf '%s\n' yes > "$OWNED_FILE"
    fi
elif [ -f "$MIRROR" ]; then
    [ -f "$OWNED_FILE" ] || fail "$MIRROR is a regular file not owned by RelayRace; refusing to overwrite it."
elif [ -e "$MIRROR" ]; then
    fail "$MIRROR exists but is neither a regular file nor a symlink."
else
    if [ ! -f "$OWNED_FILE" ]; then
        printf '%s\n' absent > "$ORIGINAL_STATE_FILE"
        rm -f "$TARGET_FILE" 2>/dev/null || true
        printf '%s\n' yes > "$OWNED_FILE"
    fi
fi

# A stale sibling .roothidepatch from the experimental v9-v15 builds must
# never load alongside the normal TweakLoader/ElleKit tweak.
rm -f "$LEGACY_PATCHER" 2>/dev/null || true

# If launchd invokes us again after this exact RootHide session is already
# fully prepared, do nothing.  v18 could kill networkserviceproxy a second time
# after postinst bootstrapped the RunAtLoad job; that was harmless but noisy.
if [ "$ACTION" = "boot" ] && \
   [ -f "$SESSION_FILE" ] && [ "$(cat "$SESSION_FILE" 2>/dev/null || true)" = "$CURRENT_JBROOT" ] && \
   [ -f "$RESET_SESSION_FILE" ] && [ "$(cat "$RESET_SESSION_FILE" 2>/dev/null || true)" = "$CURRENT_JBROOT" ] && \
   [ -f "$MIRROR" ] && [ ! -L "$MIRROR" ]; then
    if signed_mirror_is_valid "$MIRROR"; then
        if [ -n "$JBCTL" ]; then
            REAL_MIRROR=$(jb_real "$MIRROR")
            "$JBCTL" trustcache add "$REAL_MIRROR" || fail "jbctl could not trust the existing mirror."
        fi
        log "already fully prepared for this RootHide session; no action needed."
        exit 0
    fi
fi

# Package installs/upgrades always rebuild from Apple's stock binary. This is
# important when the extra entitlement profile changes. Boot-time invocations
# may reuse a valid mirror within the same RootHide session.
NEED_BUILD=1
if [ "$ACTION" = "boot" ] && [ -f "$SESSION_FILE" ] && \
   [ "$(cat "$SESSION_FILE" 2>/dev/null || true)" = "$CURRENT_JBROOT" ] && \
   [ -f "$MIRROR" ] && [ ! -L "$MIRROR" ] && signed_mirror_is_valid "$MIRROR"; then
    NEED_BUILD=0
fi

if [ "$NEED_BUILD" -eq 0 ] && [ -n "$JBCTL" ]; then
    REAL_MIRROR=$(jb_real "$MIRROR")
    "$JBCTL" trustcache add "$REAL_MIRROR" || fail "jbctl could not trust the existing mirror."
fi

if [ "$NEED_BUILD" -eq 1 ]; then
    REAL_ENTITLEMENTS=$(jb_real "$NETWORKSERVICEPROXY_ENTITLEMENTS")
    [ -n "$REAL_ENTITLEMENTS" ] || fail "Could not resolve RelayRace networkserviceproxy entitlements."

    TMP="${MIRROR}.relayrace-new.$$"
    rm -f "$TMP" 2>/dev/null || true

    cp -p "$SOURCE" "$TMP" || fail "Could not copy stock networkserviceproxy."
    chmod 0755 "$TMP"
    chown 0:0 "$TMP" 2>/dev/null || true

    REAL_TMP=$(jb_real "$TMP")
    [ -n "$REAL_TMP" ] || fail "Could not resolve temporary networkserviceproxy mirror."

    # Do not use /basebin/entitlements/bootstrap.entitlements here. It is for
    # RootHide's bootstrap executable. This dedicated profile follows
    # RootHide's resigned system-daemon pattern while -M preserves every stock
    # networkserviceproxy entitlement.
    log "Signing a RootHide networkserviceproxy mirror with the dedicated daemon profile..."
    "$LDID" -M "-S$REAL_ENTITLEMENTS" "$REAL_TMP" || fail "ldid failed; the active mirror was not replaced."
    if [ -n "$FAST_PATH_SIGN" ]; then
        "$FAST_PATH_SIGN" "$REAL_TMP" || fail "fastPathSign failed; the active mirror was not replaced."
    fi

    FINAL_ENTITLEMENTS=$("$LDID" -e "$REAL_TMP" 2>/dev/null || true)
    printf '%s\n' "$FINAL_ENTITLEMENTS" | grep -q '<key>com.apple.private.security.no-sandbox</key>' || \
        fail "Final signed mirror is missing no-sandbox; the active mirror was not replaced."
    printf '%s\n' "$FINAL_ENTITLEMENTS" | grep -q '<key>com.apple.networkd_privileged</key>' || \
        fail "Final signed mirror lost a stock networkserviceproxy entitlement; the active mirror was not replaced."
    if printf '%s\n' "$FINAL_ENTITLEMENTS" | grep -q '<key>com.apple.private.persona-mgmt</key>'; then
        fail "Final signed mirror unexpectedly contains persona-mgmt; the active mirror was not replaced."
    fi

    if [ -n "$JBCTL" ]; then
        # This trusts the signed Mach-O's code hash before activation. The
        # temporary file and final mirror are the same inode after mv.
        "$JBCTL" trustcache add "$REAL_TMP" || fail "jbctl could not trust the signed mirror; the active mirror was not replaced."
    fi

    # TMP is in the same directory as MIRROR, so rename replaces the old
    # symlink/file atomically without an unnecessary missing-file window.
    mv -f "$TMP" "$MIRROR" || fail "Could not activate the prepared networkserviceproxy mirror."
    TMP=
fi

[ -f "$MIRROR" ] && [ ! -L "$MIRROR" ] || fail "The prepared networkserviceproxy mirror is invalid."

printf '%s\n' "$CURRENT_JBROOT" > "$SESSION_FILE"
printf '%s\n' yes > "$OWNED_FILE"
chmod 0644 "$OWNED_FILE" "$ORIGINAL_STATE_FILE" "$SESSION_FILE" 2>/dev/null || true
[ ! -f "$TARGET_FILE" ] || chmod 0644 "$TARGET_FILE" 2>/dev/null || true

# Ensure an already-running stock daemon is gone so the next launch is routed
# through the prepared /.sysroot mirror and receives RootHide/ElleKit injection.
if killall -9 networkserviceproxy 2>/dev/null; then
    log "Prepared RootHide mirror and stopped the existing networkserviceproxy."
else
    log "Prepared RootHide mirror; networkserviceproxy was not running."
fi

# networkserviceproxy has a launchd/notifyd reset event. Posting it once after
# RootHide comes up clears the stale Private Relay state created before tweak
# injection was available. The randomized jbroot is the per-session guard.
SHOULD_RESET=1
if [ "$ACTION" = "boot" ] && [ -f "$RESET_SESSION_FILE" ] && \
   [ "$(cat "$RESET_SESSION_FILE" 2>/dev/null || true)" = "$CURRENT_JBROOT" ]; then
    SHOULD_RESET=0
fi

if [ "$SHOULD_RESET" -eq 1 ]; then
    sleep 1
    if "$RESET_TOOL" >/dev/null 2>&1; then
        printf '%s\n' "$CURRENT_JBROOT" > "$RESET_SESSION_FILE"
        chmod 0644 "$RESET_SESSION_FILE" 2>/dev/null || true
        log "Posted networkserviceproxy reset for the current RootHide session."
    else
        fail "Could not post com.apple.networkserviceproxy.reset."
    fi
else
    log "networkserviceproxy reset already posted for this RootHide session."
fi

exit 0
