#!/usr/bin/env bash
#
# Smart Home Kitchen-Display ISO Builder
# Target: builds a Debian 12 (Bookworm) live ISO on a Debian/Ubuntu build machine
#
# Drives `lb config && lb build` over hosts/kitchen-display/live-build/ to produce
# the fridge/pantry camera-cataloguing display described in docs/project-plan.md
# Phase 17:
#   - greetd autologin straight into a kiosk Sway session (no greeter UI)
#   - ONE Chromium kiosk window pointed at pantry-web's frontend (Scan / Inventory /
#     Recipes is in-page tab navigation, not separate Sway workspaces)
#   - kitchen-display-agent (Python, systemd) — HA MQTT "Show scan/inventory/recipes/
#     registration" buttons only; the actual camera capture, Grocy read/write, and
#     identity registration paths are pantry-vision's/identity's own published APIs,
#     called directly by the browser
#   - identity's registration page (Phase 6) — voice ("register me as <name>", needs
#     ENABLE_VOICE_SATELLITE=true and a real mic) or the touchscreen form either way
#
# Reuses hosts/thin-client's live-build toolchain and directory-split convention, not
# its live-build tree — same relationship hosts/touch-panel and hosts/audio-endpoint
# already have to the thin client's.
#
# Run as: sudo -E tools/build-kitchen-display-iso.sh [hostname]
#
# Configuration comes from CoreSystemConfig.json — see tools/README.md.

set -euo pipefail

# ---------------------------------------------------------------------------
# CONFIGURATION — comes from CoreSystemConfig.json, NOT from this file.
#
# There is nothing to edit here any more. Every value below is read from the one
# config at the repo root, so an address or token can only be wrong in a single
# place. Change it there and rebuild; see tools/README.md.
#
#   sudo -E tools/build-kitchen-display-iso.sh                 # the only kitchen-display in the config
#   sudo -E tools/build-kitchen-display-iso.sh <hostname>      # a specific one, if several are defined
#
# The build refuses to start if the config is invalid (validate-config.py runs first),
# so a typo costs seconds rather than a 40-minute build and a reboot.
# ---------------------------------------------------------------------------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib/coreconfig.sh
source "${SCRIPT_DIR}/lib/coreconfig.sh"

core_select_kiosk "kitchen-display" "${1:-}"

# Mapped onto this script's existing variable names, so everything below is unchanged
# from when these were hand-edited constants.
DEBIAN_RELEASE="$CORE_DEBIAN_RELEASE"
KIOSK_USERNAME="$CORE_KIOSK_USERNAME"
IMAGE_HOSTNAME="$CORE_KIOSK_HOSTNAME"
KEYBOARD_LAYOUT="$CORE_KEYBOARD_LAYOUT"
ENABLE_INSTALLER="$CORE_KIOSK_ENABLE_INSTALLER"
MQTT_BROKER_HOST="$CORE_MQTT_BROKER_HOST"
MQTT_BROKER_PORT="$CORE_MQTT_BROKER_PORT"
MQTT_USERNAME="$CORE_MQTT_USERNAME"
MQTT_PASSWORD="$CORE_MQTT_PASSWORD"
SSH_AUTHORIZED_KEY="$CORE_SSH_AUTHORIZED_KEY"
ENABLE_VOICE_SATELLITE="$CORE_KIOSK_VOICE_SATELLITE"
VOICE_SATELLITE_NAME="$CORE_KIOSK_FRIENDLY_NAME"
VOICE_WAKE_WORD="$CORE_KIOSK_WAKE_WORD"
KITCHEN_DISPLAY_NAME="$CORE_KIOSK_FRIENDLY_NAME"
# The HA area this device physically sits in, from the kiosk's `room` in
# CoreSystemConfig.json. The agent publishes it as suggested_area so HA files
# the device in the right room by itself — see docs/rooms-and-endpoints.md.
KITCHEN_DISPLAY_ROOM="${CORE_KIOSK_ROOM:-}"
PANTRY_WEB_URL="$CORE_PANTRY_WEB_URL"
PANTRY_VISION_URL="$CORE_PANTRY_VISION_URL"
PANTRY_VISION_TOKEN="$CORE_PANTRY_VISION_TOKEN"
IDENTITY_WEB_URL="$CORE_IDENTITY_WEB_URL"
IDENTITY_URL="$CORE_IDENTITY_URL"
IDENTITY_TOKEN="$CORE_IDENTITY_TOKEN"

# ---------------------------------------------------------------------------
# Paths — this script now lives in tools/, so the host directory it drives is
# addressed from the repo root rather than relative to the script.
# ---------------------------------------------------------------------------
KITCHEN_DISPLAY_DIR="${CORE_REPO_ROOT}/hosts/kitchen-display"
CONFIGS_DIR="${KITCHEN_DISPLAY_DIR}/configs"
AGENT_DIR="${KITCHEN_DISPLAY_DIR}/agent"
LIVE_BUILD_DIR="${KITCHEN_DISPLAY_DIR}/live-build"
INCLUDES="${LIVE_BUILD_DIR}/config/includes.chroot"
PACKAGE_LIST="${LIVE_BUILD_DIR}/config/package-lists/kitchen-display.list.chroot"

# ---------------------------------------------------------------------------
# Sanity checks
# ---------------------------------------------------------------------------
if [[ $EUID -ne 0 ]]; then
  echo "Warning: not running as root. 'lb build' needs root; re-run with: sudo $0"
  echo "  Continuing anyway so you can at least regenerate includes.chroot..."
fi

if ! command -v lb &> /dev/null; then
  if [[ $EUID -eq 0 ]]; then
    echo "--- Installing live-build ---"
    apt-get update
    apt-get install -y live-build
  else
    echo "live-build is not installed and this script is not running as root." >&2
    echo "  Install it first: sudo apt-get install live-build" >&2
    exit 1
  fi
else
  echo "--- live-build already installed, skipping ---"
fi

if [[ ! -f "$PACKAGE_LIST" ]]; then
  echo "Missing package list: $PACKAGE_LIST" >&2
  exit 1
fi




if [[ "$ENABLE_VOICE_SATELLITE" == "true" ]]; then
  echo "Note: ENABLE_VOICE_SATELLITE=true — this image expects a real microphone on"
  echo "  the physical unit. Don't flash it to hardware that doesn't have one."
fi

echo
echo "=== Smart Home Kitchen-Display ISO Builder ==="
echo "Debian release   : $DEBIAN_RELEASE"
echo "Kiosk user       : $KIOSK_USERNAME"
echo "Image hostname   : $IMAGE_HOSTNAME"
echo "MQTT broker      : ${MQTT_BROKER_HOST}:${MQTT_BROKER_PORT}"
echo "pantry-web       : $PANTRY_WEB_URL"
echo "pantry-vision    : $PANTRY_VISION_URL"
echo "identity-web     : $IDENTITY_WEB_URL"
echo "identity         : $IDENTITY_URL"
echo "Voice satellite  : $ENABLE_VOICE_SATELLITE"
echo "Keyboard layout  : $KEYBOARD_LAYOUT"
echo

# ---------------------------------------------------------------------------
# 1. Regenerate includes.chroot from configs/ and agent/
# ---------------------------------------------------------------------------
echo "--- Regenerating $INCLUDES ---"
rm -rf "$INCLUDES"
mkdir -p \
  "$INCLUDES/etc/greetd" \
  "$INCLUDES/etc/kitchen-display-agent" \
  "$INCLUDES/usr/local/bin" \
  "$INCLUDES/opt/kitchen-display-agent" \
  "$INCLUDES/home/${KIOSK_USERNAME}/.config/sway" \
  "$INCLUDES/home/${KIOSK_USERNAME}/.ssh"

subst() {
  sed -e "s/@KIOSK_USERNAME@/${KIOSK_USERNAME}/g" \
      -e "s/@KEYBOARD_LAYOUT@/${KEYBOARD_LAYOUT}/g" "$1" > "$2"
}

subst "${CONFIGS_DIR}/greetd/config.toml" "$INCLUDES/etc/greetd/config.toml"
subst "${CONFIGS_DIR}/sway/config"        "$INCLUDES/home/${KIOSK_USERNAME}/.config/sway/config"
subst "${AGENT_DIR}/kitchen-display-agent.service" "$INCLUDES/opt/kitchen-display-agent/kitchen-display-agent.service"

install -m 0755 "${CONFIGS_DIR}/greetd/kiosk-session" "$INCLUDES/usr/local/bin/kiosk-session"
install -m 0755 "${CONFIGS_DIR}/sway/pantry-kiosk"    "$INCLUDES/usr/local/bin/pantry-kiosk"
install -m 0755 "${CONFIGS_DIR}/sway/identity-kiosk"  "$INCLUDES/usr/local/bin/identity-kiosk"

mkdir -p "$INCLUDES/etc/default"
cat > "$INCLUDES/etc/default/keyboard" <<EOF
XKBMODEL="pc105"
XKBLAYOUT="${KEYBOARD_LAYOUT}"
XKBVARIANT=""
XKBOPTIONS=""

BACKSPACE="guess"
EOF

cp -r "${AGENT_DIR}/kitchen_display_agent" "$INCLUDES/opt/kitchen-display-agent/"
install -m 0644 "${AGENT_DIR}/requirements.txt" "$INCLUDES/opt/kitchen-display-agent/requirements.txt"
find "$INCLUDES/opt/kitchen-display-agent" -name '__pycache__' -type d -prune -exec rm -rf {} +

if [[ -n "$SSH_AUTHORIZED_KEY" ]]; then
  echo "$SSH_AUTHORIZED_KEY" > "$INCLUDES/home/${KIOSK_USERNAME}/.ssh/authorized_keys"
  chmod 600 "$INCLUDES/home/${KIOSK_USERNAME}/.ssh/authorized_keys"
  echo "  Baked an SSH authorized_keys entry for ${KIOSK_USERNAME}."
else
  echo "  No SSH_AUTHORIZED_KEY set — SSH admin access will not be possible on this image."
fi

# ---------------------------------------------------------------------------
# 2. Runtime config
# ---------------------------------------------------------------------------
echo "--- Writing /etc/kitchen-display-agent/config.env into includes.chroot ---"
cat > "$INCLUDES/etc/kitchen-display-agent/config.env" <<EOF
# Generated by tools/build-kitchen-display-iso.sh — do not
# hand-edit here; change CoreSystemConfig.json and rebuild.
KIOSK_USERNAME=${KIOSK_USERNAME}
KITCHEN_DISPLAY_NAME=${KITCHEN_DISPLAY_NAME}
KITCHEN_DISPLAY_ROOM=${KITCHEN_DISPLAY_ROOM}

MQTT_BROKER_HOST=${MQTT_BROKER_HOST}
MQTT_BROKER_PORT=${MQTT_BROKER_PORT}
MQTT_USERNAME=${MQTT_USERNAME}
MQTT_PASSWORD=${MQTT_PASSWORD}

PANTRY_WEB_URL=${PANTRY_WEB_URL}
PANTRY_VISION_URL=${PANTRY_VISION_URL}
PANTRY_VISION_TOKEN=${PANTRY_VISION_TOKEN}

IDENTITY_WEB_URL=${IDENTITY_WEB_URL}
IDENTITY_URL=${IDENTITY_URL}
IDENTITY_TOKEN=${IDENTITY_TOKEN}

ENABLE_VOICE_SATELLITE=${ENABLE_VOICE_SATELLITE}
VOICE_SATELLITE_NAME=${VOICE_SATELLITE_NAME}
VOICE_WAKE_WORD=${VOICE_WAKE_WORD}
EOF
chmod 0644 "$INCLUDES/etc/kitchen-display-agent/config.env"

# ---------------------------------------------------------------------------
# 3. lb config
# ---------------------------------------------------------------------------
cd "$LIVE_BUILD_DIR"

chmod +x config/hooks/normal/*.hook.chroot

if [[ -e .build ]]; then
  echo "--- Previous build found, running 'lb clean' (package cache is kept) ---"
  lb clean
fi

INSTALLER_MODE="none"
if [[ "$ENABLE_INSTALLER" == "true" ]]; then
  INSTALLER_MODE="live"
fi

echo "--- Running lb config ---"
lb config \
  --distribution "$DEBIAN_RELEASE" \
  --architectures amd64 \
  --linux-flavours amd64 \
  --archive-areas "main contrib non-free-firmware" \
  --binary-images iso-hybrid \
  --debian-installer "$INSTALLER_MODE" \
  --iso-application "SmartestHome Kitchen Display" \
  --iso-publisher "SmartestHome" \
  --iso-volume "smarthome-kitchen-display" \
  --memtest none \
  --bootappend-live "boot=live components quiet splash noautologin username=${KIOSK_USERNAME} hostname=${IMAGE_HOSTNAME}"

# ---------------------------------------------------------------------------
# 4. lb build
# ---------------------------------------------------------------------------
echo "--- Running lb build (this takes a while and needs network) ---"
lb build

ISO_PATH="$(find "$LIVE_BUILD_DIR" -maxdepth 1 -name '*.iso' -print -quit)"
ISO_PATH="${ISO_PATH:-${LIVE_BUILD_DIR}/live-image-amd64.hybrid.iso}"
# Published under this kiosk's own hostname — live-build reuses one filename per host
# tree, so two of the same kiosk type would otherwise overwrite each other.
ISO_PATH="$(core_publish_image "$ISO_PATH" "kitchen-display" "$IMAGE_HOSTNAME")"

echo
echo "=== Done ==="
echo "ISO written to:"
echo "  ${ISO_PATH}"
echo
echo "What's in it:"
echo "  greetd              : autologin as '${KIOSK_USERNAME}' straight into Sway on vt1"
echo "  Sway                : one workspace, one Chromium kiosk window"
echo "  Kiosk page          : ${PANTRY_WEB_URL}/index.html (Scan / Inventory / Recipes tabs)"
echo "  Camera              : getUserMedia in Chromium (--use-fake-ui-for-media-stream"
echo "                        auto-accepts the permission prompt), not a native capture app"
echo "  kitchen-display-agent: system service, MQTT ${MQTT_BROKER_HOST}:${MQTT_BROKER_PORT}"
echo "  Registration        : ${IDENTITY_WEB_URL}/register.html, on 'Show registration'"
echo "                        (MQTT) or by voice once ENABLE_VOICE_SATELLITE=true — see"
echo "                        identity/README.md"
if [[ "$ENABLE_VOICE_SATELLITE" == "true" ]]; then
  echo "  Voice satellite     : wyoming-satellite + openWakeWord ('${VOICE_WAKE_WORD}'), room"
  echo "                        '${VOICE_SATELLITE_NAME}'"
else
  echo "  Voice satellite     : NOT installed (ENABLE_VOICE_SATELLITE=false) — registration"
  echo "                        still works via the touchscreen form"
fi
echo "  Keyboard layout     : ${KEYBOARD_LAYOUT} (console + Sway)"
echo "  Maintenance shell   : Super+Shift+Ctrl+M opens a floating terminal locally"
echo "  Remote admin        : SSH only — no wayvnc, same scope decision as hosts/touch-panel"
echo
echo "Next steps:"
echo "  1. Write the ISO to a USB stick:"
echo "       sudo dd if=${ISO_PATH} of=/dev/sdX bs=4M status=progress oflag=sync"
echo "     (double-check /dev/sdX with 'lsblk' first)"
echo "  2. Boot the target machine — a webcam pointed at the counter/fridge front is"
echo "     required hardware, not built in; see the README for what's assumed about it."
echo "  3. Confirm greetd autologin lands in Sway with the Chromium kiosk window up."
echo "  4. Grant/verify camera access: --use-fake-ui-for-media-stream should skip the"
echo "     prompt entirely; if the Scan tab shows a camera error, check"
echo "     'v4l2-ctl --list-devices' and that Chromium picked the right one (Chromium"
echo "     defaults to the system default video input — untested on real hardware)."
echo "  5. Confirm kitchen-display-agent connected and registered:"
echo "       systemctl status kitchen-display-agent"
echo "     In Home Assistant, a '${KITCHEN_DISPLAY_NAME}' device should appear under the"
echo "     MQTT integration with: Show scan / Show inventory / Show recipes (buttons)."
echo "  6. Hold a grocery item up to the camera, tap Capture, and confirm a proposal"
echo "     comes back from pantry-vision within a few seconds — first checkpoint for"
echo "     whether the chosen Ollama vision model's latency is workable at all."
echo "  7. Tap 'Show registration' (or the HA button) and register yourself via the"
echo "     touchscreen form — this exercises the whole identity path without needing"
echo "     voice or HA's intent-script wiring set up first. See identity/README.md"
echo "     for TRUSTED_ENTITY_PREFIXES — registration will report 'no candidate' until"
echo "     that's set to match your real Private BLE Device / fixed-tag entity IDs."
if [[ "$ENABLE_VOICE_SATELLITE" == "true" ]]; then
  echo "  8. Once HA's custom-sentence + intent script (identity/README.md's worked"
  echo "     example) are wired up, say 'register me as <name>' and confirm the same"
  echo "     result happens via voice."
fi
echo
echo "Then pull the power on the container host and re-check: the kiosk must still"
echo "boot (Scan/Inventory/Recipes will show connection errors, which is the expected"
echo "degraded state — this device has no local fallback data source, same acceptance"
echo "already documented for hosts/touch-panel's Home workspace)."
echo
echo "Rebuilding later: edit hosts/kitchen-display/configs/* or agent/*, then re-run"
echo "this script — includes.chroot is regenerated from them every time."
