#!/bin/bash
# The upgrade that failed, reproduced on purpose.
#
# A real classroom does not arrive new, and the clean-install test was
# passing on a machine that had never been anything else. This builds a
# machine that has: the Hyprland experiment package actually installed,
# with sway, waybar and mako behind it, a Waybar activated through
# graphical-session, an autostart entry, a device.conf still asking for a
# compositor that is gone, and a Plasma profile belonging to a different
# desktop. Then it installs the classroom package over the top and asks
# whether the room converged.
#
#   tools/lab/dirty-upgrade [NEW.deb] [OLD.deb]
#   CHECK_ARGS=--restart tools/lab/dirty-upgrade   ask twice, either side
#                                                  of a logout
#
# The container is restarted between the install and the session, because
# a room takes its upgrade and reboots.
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
LAB="$ROOT/tools/lab/lab"
NAME="${LAB_NAME:-classroom-v2-lab}"

NEW="${1:-$(ls -t "$ROOT"/dist/ekklesia-classroom_*_amd64.deb | grep -v '~' | head -1)}"
OLD="${2:-$ROOT/dist/ekklesia-classroom_0.1.45~hypr3_amd64.deb}"

step() { printf '\n\033[1m== %s\033[0m\n' "$1"; }

step "a fresh machine"
"$LAB" up >/dev/null

docker exec "$NAME" sh -c '
    printf "#!/bin/sh\nexit 101\n" > /usr/sbin/policy-rc.d
    chmod +x /usr/sbin/policy-rc.d
    apt-get update -qq >/dev/null 2>&1
    # The old package schedules a provisioning run that would go to
    # backports for Hyprland. The lab is not testing that.
    systemctl mask ekklesia-classroom-provision.service >/dev/null 2>&1'

step "the old classroom: $(basename "$OLD")"
docker exec "$NAME" sh -c "
    DEBIAN_FRONTEND=noninteractive dpkg -i '/srv/classroom/${OLD#$ROOT/}' >/dev/null 2>&1
    DEBIAN_FRONTEND=noninteractive apt-get -y -qq -f install >/dev/null 2>&1
    DEBIAN_FRONTEND=noninteractive dpkg --configure ekklesia-classroom >/dev/null 2>&1
    true" || true
docker exec "$NAME" dpkg-query -W -f='  installed: ${Version}\n' ekklesia-classroom

step "and everything a used machine accumulates"
docker exec -i "$NAME" bash <<'DIRT'
set -e

# Waybar and mako, activated the way the real room had them. Neither
# package ships a unit in trixie, so the units themselves are part of what
# somebody added — and one of the three activation directories is the one
# the broken room actually used.
for unit in waybar mako; do
    cat > "/etc/systemd/user/$unit.service" <<UNIT
[Unit]
Description=$unit (left over from the old classroom shell)
PartOf=graphical-session.target
After=graphical-session.target

[Service]
ExecStart=/usr/bin/$unit
Restart=on-failure

[Install]
WantedBy=graphical-session.target
UNIT
done

for dir in /etc/systemd/user /etc/xdg/systemd/user \
           /home/classroom/.config/systemd/user; do
    mkdir -p "$dir/graphical-session.target.wants"
    ln -sf /etc/systemd/user/waybar.service \
        "$dir/graphical-session.target.wants/waybar.service"
    ln -sf /etc/systemd/user/mako.service \
        "$dir/graphical-session.target.wants/mako.service"
done

# An autostart entry as well, for a bar that is started two ways.
mkdir -p /home/classroom/.config/autostart
cat > /home/classroom/.config/autostart/waybar.desktop <<'ENTRY'
[Desktop Entry]
Type=Application
Name=Waybar
Exec=waybar
ENTRY

# The room still asking for a compositor that is gone, with a broker
# password in the same file to prove the migration does not rewrite it.
sed -i 's/^CHANNEL=.*/CHANNEL=hyprland/' /etc/ekklesia-classroom/device.conf
{
    echo "COMPOSITOR=hyprland"
    echo "HYPR_APPEARANCE=visual"
} >> /etc/ekklesia-classroom/device.conf
sed -i 's/^MQTT_HOST=.*/MQTT_HOST=broker.example.invalid/' /etc/ekklesia-classroom/device.conf
sed -i 's/^MQTT_PASSWORD=.*/MQTT_PASSWORD=keep-me-exactly/' /etc/ekklesia-classroom/device.conf

# A Plasma profile from a different desktop: someone else's palette, in
# both of the places that outrank the package.
mkdir -p /home/classroom/.config/kdedefaults
cat > /home/classroom/.config/kdedefaults/kdeglobals <<'KDE'
[General]
ColorScheme=BreezeLight

[Icons]
Theme=breeze

[KDE]
LookAndFeelPackage=org.kde.breeze.desktop
KDE
cat > /home/classroom/.config/kdeglobals <<'KDE'
[General]
ColorScheme=BreezeLight

[Colors:Window]
BackgroundNormal=239,240,241
ForegroundNormal=35,38,41

[KDE]
LookAndFeelPackage=org.kde.breeze.desktop
KDE

# And a stock panel, already built, of the kind the broken upgrade made.
cat > /home/classroom/.config/plasma-org.kde.plasma.desktop-appletsrc <<'PANEL'
[Containments][1]
plugin=org.kde.plasma.folder

[Containments][2]
plugin=org.kde.panel

[Containments][2][Applets][3]
plugin=org.kde.plasma.kickoff

[Containments][2][Applets][4]
plugin=org.kde.plasma.pager

[Containments][2][Applets][5]
plugin=org.kde.plasma.icontasks

[Containments][2][Applets][5][Configuration][General]
launchers=applications:systemsettings.desktop,applications:org.kde.discover.desktop,preferred://browser

[Containments][2][Applets][6]
plugin=org.kde.plasma.systemtray
PANEL

# A user-level power profile that would suspend the room.
cat > /home/classroom/.config/powermanagementprofilesrc <<'POWER'
[AC][SuspendSession]
idleTime=1800000
suspendType=1

[AC][DPMSControl]
idleTime=600
POWER

chown -R classroom:classroom /home/classroom/.config
echo "  dirt in place"
DIRT

step "the new classroom: $(basename "$NEW")"
docker exec "$NAME" sh -c '
    systemctl unmask ekklesia-classroom-provision.service >/dev/null 2>&1 || true'
docker exec "$NAME" sh -c "
    DEBIAN_FRONTEND=noninteractive dpkg -i '/srv/classroom/${NEW#$ROOT/}' 2>&1 \
        | grep -E '^\[classroom-migrate\]' || true
    DEBIAN_FRONTEND=noninteractive apt-get -y -qq -f install >/dev/null 2>&1
    DEBIAN_FRONTEND=noninteractive dpkg --configure ekklesia-classroom >/dev/null 2>&1
    rm -f /usr/sbin/policy-rc.d
    true" || true
docker exec "$NAME" dpkg-query -W -f='  installed: ${Version} ${db:Status-Abbrev}\n' ekklesia-classroom

step "and the room reboots"
"$LAB" reboot

step "the session"
"$LAB" session >/dev/null
sleep 6

step "did it converge?"
converged=0
"$ROOT/tools/lab/converged-check" ${CHECK_ARGS:-} || converged=1

step "and again, installed a second time over itself"
# An update that changes nothing must change nothing. The migration runs
# again here, over a machine that is already converged.
docker exec "$NAME" sh -c "
    DEBIAN_FRONTEND=noninteractive dpkg -i '/srv/classroom/${NEW#$ROOT/}' >/dev/null 2>&1
    true" || true
before=$(docker exec "$NAME" sh -c 'cat /etc/ekklesia-classroom/device.conf | sha256sum')
"$LAB" plasma-down >/dev/null
"$LAB" plasma-up >/dev/null
sleep 4
after=$(docker exec "$NAME" sh -c 'cat /etc/ekklesia-classroom/device.conf | sha256sum')
[[ "$before" == "$after" ]] \
    && echo "  device.conf unchanged by the second install" \
    || { echo "  DEVICE.CONF CHANGED ON REINSTALL"; converged=1; }
"$ROOT/tools/lab/converged-check" || converged=1

step "and the room's own theme choice survives a logout"
# Deleting the look and feel defaults every login was measured to make
# Plasma re-apply the look and feel and throw the room's chosen palette
# away with it. This is the check that stops that coming back.
# With the session's own cascade. plasma-apply-colorscheme writes the
# chosen name into ~/.config/kdedefaults, which is in XDG_CONFIG_DIRS for
# a session and not for a bare command, so asking without it reports
# nothing and means nothing.
theme() {
    local dirs
    dirs=$(docker exec "$NAME" bash -c 'p=$(pgrep -x plasmashell | head -1); tr "\0" "\n" < /proc/$p/environ | grep "^XDG_CONFIG_DIRS=" | cut -d= -f2-')
    docker exec -u classroom -e XDG_RUNTIME_DIR=/run/user/1000 \
        -e DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus \
        -e WAYLAND_DISPLAY=wayland-0 -e "XDG_CONFIG_DIRS=$dirs" "$NAME" \
        /usr/local/bin/classroom-theme "$1" 2>/dev/null | tail -1
}
theme light >/dev/null
"$LAB" plasma-down >/dev/null
"$LAB" plasma-up >/dev/null
sleep 4
chosen=$(theme show)
if [[ "$chosen" == EkklesiaLight ]]; then
    echo "  light survived the logout"
else
    echo "  THE ROOM'S THEME CHOICE WAS LOST: $chosen"
    converged=1
fi
theme dark >/dev/null
echo "  back to $(theme show)"

step "and it still recovers"
"$ROOT/tools/lab/recovery-check" || converged=1

exit "$converged"
