#!/usr/bin/env bash
# appliance-macos.sh - lock a Mac into a kraken-player kiosk. Run with sudo AFTER
# install-macos.sh (which installs the binary + the per-user LaunchAgent):
#
#   sudo ./scripts/appliance-macos.sh [kiosk-username]
#
# What it configures (idempotent - safe to re-run):
#   - passwordless sudo for ONLY the commands the player needs (systemsetup, pmset,
#     shutdown) - so SET_TIMEZONE / SYNC_TIME / SCREEN_POWER / REBOOT work unattended
#   - screensaver off + no password-on-wake (so the sign never locks)
#   - system + display never sleep (pmset)
#   - Dock auto-hidden
# The LaunchAgent from install-macos.sh runs the player in the logged-in GUI
# session (Chromium needs Aqua), so a desktop session must exist - enable autologin
# (documented at the end; kcpassword obfuscation is intentionally NOT scripted).
#
# NOTE: OS-level automation that can't run in CI. Validate on real Mac hardware.
# macOS players are BYO (the supplied appliance is Raspberry Pi); this is for
# operators who run a Mac as a dedicated sign.
set -euo pipefail

if [[ "${EUID}" -ne 0 ]]; then
  echo "Run as root: sudo $0 [kiosk-username]" >&2
  exit 1
fi

KIOSK_USER="${1:-${KIOSK_USER:-${SUDO_USER:-}}}"
if [[ -z "${KIOSK_USER}" ]]; then
  echo "Provide the kiosk username: sudo $0 <username>" >&2
  exit 1
fi
if ! id "${KIOSK_USER}" >/dev/null 2>&1; then
  echo "User '${KIOSK_USER}' does not exist." >&2
  exit 1
fi

echo "==> Verifying the player's system binaries exist..."
for bin in /usr/sbin/systemsetup /usr/bin/pmset /sbin/shutdown; do
  if [[ ! -x "${bin}" ]]; then
    echo "Required binary ${bin} not found on this macOS; aborting (won't grant sudo to a missing path)." >&2
    exit 1
  fi
done

echo "==> Passwordless sudo for the player's system commands (kiosk only)..."
SUDOERS="/etc/sudoers.d/kraken-player"
# Scoped to the EXACT commands + argument shapes the darwin platform layer runs
# (platform_darwin.go: SET_TIMEZONE / SYNC_TIME / SCREEN_POWER / REBOOT), so a
# compromised kiosk user can't use these binaries to, e.g., enable remote login.
cat > "${SUDOERS}" <<EOF
# Managed by appliance-macos.sh - lets ${KIOSK_USER} run ONLY the player's
# unattended system commands (specific arguments only) without a password.
${KIOSK_USER} ALL=(root) NOPASSWD: /usr/sbin/systemsetup -settimezone *
${KIOSK_USER} ALL=(root) NOPASSWD: /usr/sbin/systemsetup -setusingnetworktime on
${KIOSK_USER} ALL=(root) NOPASSWD: /usr/bin/pmset -a displaysleep *
${KIOSK_USER} ALL=(root) NOPASSWD: /sbin/shutdown -r now
EOF
chmod 0440 "${SUDOERS}"
# Validate (showing diagnostics) + confirm it wrote non-empty; a bad/partial
# drop-in must be removed rather than left to break sudo system-wide.
if ! visudo -cf "${SUDOERS}"; then
  echo "sudoers validation failed (see above); removing ${SUDOERS}" >&2
  rm -f "${SUDOERS}"
  exit 1
fi
if [[ ! -s "${SUDOERS}" ]]; then
  echo "sudoers drop-in empty after write; removing ${SUDOERS}" >&2
  rm -f "${SUDOERS}"
  exit 1
fi

echo "==> Enabling allowSystemCommands (else SET_VOLUME/TIMEZONE/POWER silently no-op)..."
# The player gates system commands behind config.allowSystemCommands. The sudoers
# grant above is useless without this flag flipped on.
CONFIG="/usr/local/var/kraken-player/config.json"
# Use the python invocation itself AS the if-condition: a command that fails in an
# if-test does NOT trip `set -e`, so a missing config or a Command-Line-Tools python
# STUB (present as a file but exits non-zero) degrades to the manual hint instead of
# aborting the whole appliance setup.
if [[ -f "${CONFIG}" ]] && /usr/bin/python3 - "${CONFIG}" <<'PY'
import json, sys
p = sys.argv[1]
try:
    d = json.load(open(p))
except Exception:
    d = {}
d["allowSystemCommands"] = True
json.dump(d, open(p, "w"), indent=2)
PY
then
  echo "  allowSystemCommands=true"
else
  echo "  (set \"allowSystemCommands\": true in ${CONFIG} by hand - config missing or no python3)"
fi

echo "==> Screensaver off + no password on wake (for ${KIOSK_USER})..."
sudo -u "${KIOSK_USER}" defaults -currentHost write com.apple.screensaver idleTime -int 0 2>/dev/null || echo "  (warning: screensaver idleTime not set; home dir inaccessible or MDM-managed?)"
sudo -u "${KIOSK_USER}" defaults write com.apple.screensaver askForPassword -int 0 2>/dev/null || echo "  (warning: screensaver askForPassword not set)"
sudo -u "${KIOSK_USER}" defaults write com.apple.screensaver askForPasswordDelay -int 0 2>/dev/null || echo "  (warning: screensaver askForPasswordDelay not set)"

echo "==> System + display never sleep..."
pmset -a sleep 0 2>/dev/null || echo "  (warning: pmset sleep not set)"
pmset -a displaysleep 0 2>/dev/null || echo "  (warning: pmset displaysleep not set)"
pmset -a disksleep 0 2>/dev/null || echo "  (warning: pmset disksleep not set)"

echo "==> Auto-hide the Dock (for ${KIOSK_USER})..."
sudo -u "${KIOSK_USER}" defaults write com.apple.dock autohide -bool true 2>/dev/null || echo "  (warning: Dock autohide not set)"
sudo -u "${KIOSK_USER}" defaults write com.apple.dock autohide-delay -float 1000 2>/dev/null || echo "  (warning: Dock autohide-delay not set)"
sudo -u "${KIOSK_USER}" killall Dock 2>/dev/null || true

echo ""
echo "Lockdown applied. One manual step remains - enable AUTOMATIC LOGIN for"
echo "'${KIOSK_USER}' so a GUI session exists at boot for the player's Chromium:"
echo "  System Settings > Users & Groups > Automatic login > ${KIOSK_USER}"
echo "(Automatic-login password handling is intentionally left to the OS UI rather"
echo " than scripting the obfuscated /etc/kcpassword file.)"
echo "Then reboot. The LaunchAgent starts the player in the kiosk session."
