#!/usr/bin/env bash

# What the session starts, the session must stop.
#
# autostart.lua starts about ten user units on hyprland.start. None of them is
# a child of the compositor, so when Hyprland exits they keep running -- and
# each one carries Requires=graphical-session.target, so that target stays
# active with no session behind it.
#
# The shutdown handler was supposed to prevent exactly that, and did not: it
# stopped `hyprland-session.target`, a unit Fedora does not ship. systemctl
# reports "Unit not found" and exits, the handler reports nothing, and the
# stale session survives to the login screen.
#
# The symptom was not a broken Hyprland. It was that "Hyprland (uwsm-managed)"
# and GNOME both bounced back to the login screen -- both refuse to start into
# a session that is already running -- while plain Hyprland, which makes no
# such check, kept working. The one session that appeared healthy was the one
# doing the damage.
#
# Pinned here because the failure is silent in both directions: a handler that
# stops nothing looks identical to one that works, until the next login.

set -uo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
autostart="$repo_dir/config/dot/hypr/autostart.lua"

findings=()
note() { findings+=("$1"); }

[[ -r "$autostart" ]] || { printf 'session teardown contract: no autostart.lua\n' >&2; exit 1; }

# Comments stripped: the header above the handler explains the whole bug at
# length, and matching that would be matching documentation rather than code.
uncommented() { grep -vE '^\s*--' "$autostart"; }

shutdown_body="$(uncommented | sed -n '/hl\.on("hyprland\.shutdown"/,/^end)/p')"

[[ -n "$shutdown_body" ]] \
    || note 'there is no hyprland.shutdown handler, so nothing tears the session down'

# ── It must stop something that exists ──────────────────────────────────────

grep -q 'hyprland-session\.target' <<<"$shutdown_body" \
    && note 'the shutdown handler stops hyprland-session.target, which Fedora does not ship -- it is a no-op'

grep -q 'stop graphical-session\.target' <<<"$shutdown_body" \
    || note 'the shutdown handler does not stop graphical-session.target, so the units outlive the session'

# ── The mechanism it relies on ──────────────────────────────────────────────
#
# Stopping the target only takes the units with it while they are PartOf= it.
# A unit shipped without that line would survive the teardown and hold the
# target back up, which is the original bug wearing a different hat.

units_dir="$repo_dir/config/local/share/systemd/user"
if [[ -d "$units_dir" ]]; then
    for unit in "$units_dir"/*.service; do
        [[ -e "$unit" ]] || continue
        name="$(basename "$unit")"

        # Only the ones the session starts and expects to outlive nothing. A
        # oneshot notifier exits on its own and needs no teardown.
        grep -q "start .*$name" "$autostart" || continue
        grep -qE '^\s*Type\s*=\s*oneshot' "$unit" && continue

        grep -qE '^\s*PartOf\s*=.*graphical-session\.target' "$unit" \
            || note "$name is started by the session but is not PartOf graphical-session.target, so it survives logout"
    done
fi

if (( ${#findings[@]} > 0 )); then
    printf 'session teardown contract: %d finding(s)\n' "${#findings[@]}" >&2
    printf '  - %s\n' "${findings[@]}" >&2
    exit 1
fi

printf 'session teardown contract: PASS\n'
