#!/usr/bin/env bash

# What closing the lid does.
#
# One sentence: closing the lid should suspend, unless there is an external
# monitor, in which case the machine is docked and should keep working.
#
# The mechanism is a logind `handle-lid-switch` inhibitor held while an
# external display is connected, rather than a lid watcher of Panama's own.
# That choice is the thing most worth pinning, because the obvious alternative
# fails in the dangerous direction: a drop-in setting HandleLidSwitch=ignore
# plus a watcher that dies leaves a laptop whose lid does nothing at all, being
# carried out of a building. An inhibitor that dies gives back logind's
# default, which is merely an annoying suspend at a desk.
#
# So this asserts, in order of how much it would cost to get wrong:
#
#   1. No logind drop-in is shipped. Panama never takes the lid over.
#   2. A machine with no reason for an inhibitor holds none: a desktop, and an
#      undocked laptop that should suspend normally.
#   3. A docked laptop holds one, and it is the right kind.
#   4. Locking on the way down is not this code's job -- hypridle's
#      before_sleep_cmd already does it -- and must not be quietly duplicated.
#
# Driven with stubbed predicates. The end-to-end behavior of a real lid needs a
# machine with a lid; see the header of the helper.

set -uo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
helper="$repo_dir/config/dot/quickshell/scripts/panama-lid"
service="$repo_dir/config/dot/quickshell/services/LidPolicy.qml"
shell_qml="$repo_dir/config/dot/quickshell/shell.qml"
hypridle="$repo_dir/config/dot/hypr/hypridle.conf"

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

[[ -x "$helper" ]] || { printf 'lid contract: %s is not executable\n' "$helper" >&2; exit 1; }

work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT
calls="$work/calls"
fake="$work/fake"
mkdir -p "$fake/bin"

# ── 1. Panama never takes the lid over ───────────────────────────────────────

# Specifically the LID. Other keys may be configured there -- the power-key
# drop-in is deliberate policy with a compositor bind behind it -- but a
# HandleLidSwitch line would replace the inhibitor design this file protects.
if compgen -G "$repo_dir/config/copy/etc/systemd/logind.conf.d/*" >/dev/null 2>&1 \
    && sed 's/#.*//' "$repo_dir"/config/copy/etc/systemd/logind.conf.d/* | grep -q 'HandleLidSwitch'; then
    note 'a logind drop-in sets HandleLidSwitch; the inhibitor approach exists so the lid is never left doing nothing'
fi
# Comments are stripped first: these files explain at length what they
# deliberately do NOT do, and prose naming HandleLidSwitch or lock-session is
# documentation rather than behavior.
uncommented() { grep -rhv '^[[:space:]]*#' "$@" 2>/dev/null; }

uncommented "$repo_dir/config" | grep -q 'HandleLidSwitch' \
    && note 'something sets HandleLidSwitch, which takes the lid away from logind'

# ── The stubs ────────────────────────────────────────────────────────────────

# panama-hw answers whatever this fixture says. $1 laptop, $2 external monitor,
# as exit codes: 0 yes, 1 no.
stub_hw() {
    cat >"$fake/bin/panama-hw" <<STUB
#!/usr/bin/env bash
case "\$1" in
    laptop)           exit $1 ;;
    external-monitor) exit $2 ;;
    lid-closed)       exit 1 ;;
    clamshell)        exit 1 ;;
    *)                exit 1 ;;
esac
STUB
    chmod +x "$fake/bin/panama-hw"
}

# systemd-inhibit records how it was called instead of holding anything.
cat >"$fake/systemd-inhibit" <<STUB
#!/usr/bin/env bash
printf '%s\n' "\$*" >>"$calls"
STUB
chmod +x "$fake/systemd-inhibit"

guard() {
    : >"$calls"
    PATH="$fake:$PATH" PANAMA_PATH="$fake" "$helper" guard >/dev/null 2>&1
}

# ── 2. Machines that should hold nothing ─────────────────────────────────────

stub_hw 1 0   # a desktop: not a laptop, external monitor present
guard || note 'the guard failed on a desktop instead of exiting cleanly'
[[ -s "$calls" ]] && note 'a desktop held a lid inhibitor, which it has no lid to inhibit'

stub_hw 0 1   # a laptop with no external display: must suspend normally
guard || note 'the guard failed on an undocked laptop instead of exiting cleanly'
[[ -s "$calls" ]] \
    && note 'an undocked laptop held a lid inhibitor, so closing it in a bag would not suspend'

# ── 3. A docked laptop holds the right one ───────────────────────────────────

stub_hw 0 0   # a laptop with an external display
guard
[[ -s "$calls" ]] || note 'a docked laptop held no inhibitor, so closing the lid would suspend mid-work'
recorded="$(cat "$calls" 2>/dev/null)"
grep -q -- '--what=handle-lid-switch' <<<"$recorded" \
    || note 'the inhibitor is not a handle-lid-switch inhibitor, so logind would still act on the lid'
grep -q -- '--mode=block' <<<"$recorded" \
    || note 'the inhibitor is a delay rather than a block, so logind would suspend anyway after its timeout'
grep -q -- '--who=panama-lid' <<<"$recorded" \
    || note 'the inhibitor does not identify itself, so systemd-inhibit --list cannot explain who is holding it'
grep -q -- '--why=' <<<"$recorded" \
    || note 'the inhibitor states no reason'

# ── 4. Locking on the way down stays hypridle's job ──────────────────────────

grep -q 'before_sleep_cmd' "$hypridle" \
    || note 'the shipped hypridle config no longer locks before sleep, which is what makes a lid-close suspend a locked one'
uncommented "$helper" | grep -q 'loginctl lock-session\|hyprlock' \
    && note 'the lid helper locks the session itself, duplicating what hypridle already does on every sleep'

# ── The service that drives it ───────────────────────────────────────────────

[[ -r "$service" ]] || note 'LidPolicy.qml is missing, so nothing notices a display being connected'
grep -q 'eDP|LVDS|DSI' "$service" \
    || note 'the service does not distinguish the built-in panel from an external display'
grep -q 'Connections { target: LidPolicy }' "$shell_qml" \
    || note 'nothing keeps LidPolicy alive, so it would only start when some page happened to reference it'

# Status is machine-readable, for the Power page and panama-doctor.
stub_hw 0 0
status="$(PATH="$fake:$PATH" PANAMA_PATH="$fake" "$helper" status 2>/dev/null)"
if command -v jq >/dev/null 2>&1; then
    jq -e . >/dev/null 2>&1 <<<"$status" || note 'status does not emit valid JSON'
    for key in laptop lidClosed externalMonitor clamshell inhibited; do
        jq -e "has(\"$key\")" >/dev/null 2>&1 <<<"$status" || note "status omits $key"
    done
fi

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

printf 'lid contract: PASS\n'
