#!/usr/bin/env bash

# The lock screen follows the color scheme.
#
# It did not. hyprlock.conf shipped with Tokyo Night Moon hardcoded in six
# places, so choosing light mode left the one screen a user sees most often
# stubbornly dark. Every other surface -- kitty, GTK, the launcher, btop, tmux,
# neovim -- had been taught to follow the scheme; this was the last one.
#
# It is also the worst place to discover a theming bug, because you find out
# while locked out of the machine and cannot fix it from there. Hence a test.
#
# Generated into a fixture, never the live config: this contract must not
# retheme the lock screen of the desktop it is running on.

set -uo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
template="$repo_dir/config/dot/hypr/hyprlock.conf.template"
theme_apps="$repo_dir/config/dot/quickshell/scripts/panama-theme-apps"

fail() {
    printf 'lock screen theme contract: %s\n' "$1" >&2
    exit 1
}

[[ -r "$template" ]] || fail 'hyprlock.conf.template is missing, so nothing generates the lock screen'

# The committed template must carry no literal colors. One left behind is a
# color that silently stays dark in light mode -- exactly the original bug.
literal="$(grep -vE '^\s*#' "$template" | grep -oE 'rgba\([0-9]+, *[0-9]+, *[0-9]+' || true)"
[[ -z "$literal" ]] \
    || fail "the template still contains hardcoded colors, which will not follow the scheme: $literal"

# ── The colours are written down once ────────────────────────────────────────
# They used to be three copies of the same two tables: one here in
# panama-theme-apps, one in panama-lock, one in setup/scripts/link-dotfiles.
# The copy that got missed was always the seed, because a wrong seed only shows
# up the first time somebody locks a fresh machine -- and by then they are
# locked out of the machine they would fix it on.
helper="$repo_dir/config/dot/quickshell/scripts/panama-palette"
lock_script="$repo_dir/config/dot/quickshell/scripts/panama-lock"
linker="$repo_dir/setup/scripts/link-dotfiles"

grep -q '^render_hyprlock()' "$helper" \
    || fail 'panama-palette does not define render_hyprlock, so the eight substitutions have gone back to living per-caller'
for consumer in "$theme_apps" "$linker"; do
    grep -q 'render_hyprlock' "$consumer" \
        || fail "$(basename "$consumer") no longer fills the template through the shared renderer"
done
grep -q 'resolve_theme' "$lock_script" \
    || fail 'panama-lock no longer resolves the theme through the shared resolver, so it has its own palette again'

# A quoted decimal triple in any of them is the table growing back.
for consumer in "$theme_apps" "$lock_script" "$linker"; do
    restated="$(grep -vE '^\s*#' "$consumer" \
        | grep -oE "['\"][0-9]{1,3}, [0-9]{1,3}, [0-9]{1,3}['\"]" || true)"
    [[ -z "$restated" ]] \
        || fail "$(basename "$consumer") carries hardcoded lock-screen colors again: $restated"
done

fixture="$(mktemp -d /tmp/panama-lockscreen.XXXXXX)"
trap 'rm -rf "$fixture"' EXIT
mkdir -p "$fixture/hypr"
cp "$template" "$fixture/hypr/"

for scheme in dark light; do
    XDG_CONFIG_HOME="$fixture" "$theme_apps" "$scheme" >/dev/null 2>&1
    generated="$fixture/hypr/hyprlock.conf"

    [[ -r "$generated" ]] || fail "no hyprlock.conf was generated for $scheme"

    # An unsubstituted placeholder is not a parse error to hyprlock; it is an
    # invalid color it quietly ignores, falling back to its own default.
    leftover="$(grep -oE '@[A-Z_]+@' "$generated" || true)"
    [[ -z "$leftover" ]] \
        || fail "$scheme left placeholders unsubstituted: $leftover"

    # Every color hyprlock is given must be a complete decimal triple. It
    # takes rgba(r, g, b, a), NOT hex, and a hex value here is silently ignored.
    while read -r color; do
        [[ -n "$color" ]] || continue
        grep -qE '^rgba\([0-9]{1,3}, [0-9]{1,3}, [0-9]{1,3}$' <<<"$color" \
            || fail "$scheme produced a malformed color: $color"
    done < <(grep -vE '^\s*#' "$generated" | grep -oE 'rgba\([^)]*' | sed 's/,[^,]*$//')

    # The Pango markup values are hex, and hyprlock wants them doubled-hashed.
    while read -r pango; do
        [[ -n "$pango" ]] || continue
        grep -qE '^##[0-9a-f]{6}$' <<<"$pango" \
            || fail "$scheme produced malformed Pango markup color: $pango"
    done < <(grep -vE '^\s*#' "$generated" | grep -oE '##[0-9a-fA-F]{6}')

    # The whole background block, not a fixed number of lines after it: the
    # color sits near the end, after the blur and noise settings.
    background="$(awk '/^background \{/,/^\}/' "$generated" \
        | grep -vE '^\s*#' | grep -oE 'color = rgba\([0-9]+' | grep -oE '[0-9]+$' | head -1)"
    [[ -n "$background" ]] || fail "$scheme produced no background color"

    # The point of the whole exercise: a light lock screen must actually be
    # light. 128 splits the two cleanly for these palettes.
    if [[ "$scheme" == "light" ]]; then
        (( background > 128 )) \
            || fail "light mode produced a DARK lock screen background (red channel $background) -- the original bug"
    else
        (( background < 128 )) \
            || fail "dark mode produced a LIGHT lock screen background (red channel $background)"
    fi
done

# The two schemes must actually differ, or the substitution is a no-op that
# passes every check above.
XDG_CONFIG_HOME="$fixture" "$theme_apps" dark >/dev/null 2>&1
dark_hash="$(sha256sum "$fixture/hypr/hyprlock.conf" | cut -d' ' -f1)"
XDG_CONFIG_HOME="$fixture" "$theme_apps" light >/dev/null 2>&1
light_hash="$(sha256sum "$fixture/hypr/hyprlock.conf" | cut -d' ' -f1)"
[[ "$dark_hash" != "$light_hash" ]] \
    || fail 'the light and dark lock screens are byte-identical, so the scheme is not being applied'

# ── A THEME reaches it, not only a scheme ────────────────────────────────────
# The lock screen followed light and dark long before it followed themes:
# choosing Catppuccin restyled the shell, the terminal and the launcher, and
# left the lock screen in Tokyo Night.
catalog="$repo_dir/config/dot/quickshell/config/themes.json"
if [[ -r "$catalog" ]]; then
    default_dark="$(jq -r '.defaultDark' "$catalog")"
    # A theme whose BACKGROUND differs from the default's, not merely its id:
    # Moon Rose is Moon's palette with another accent, and asserting against it
    # would pass even if the generator ignored the theme entirely.
    other="$(jq -r --arg default "$default_dark" '
        (.themes[] | select(.id == $default) | .palette.bg) as $base
        | [.themes[] | select(.scheme == "dark" and .palette.bg != $base)][0].id' "$catalog")"

    if [[ -n "$other" && "$other" != "null" ]]; then
        want="$(jq -r --arg id "$other" '.themes[] | select(.id == $id) | .palette.bg' "$catalog")"
        triple="$(printf '%d, %d, %d' "0x${want:1:2}" "0x${want:3:2}" "0x${want:5:2}")"

        mkdir -p "$fixture/panama"
        jq -n --arg id "$other" '{colorScheme: "dark", themeProfileId: $id}' \
            >"$fixture/panama/settings.json"
        XDG_CONFIG_HOME="$fixture" "$theme_apps" dark >/dev/null 2>&1

        grep -q "rgba($triple, 1.0)" "$fixture/hypr/hyprlock.conf" \
            || fail "selecting the \"$other\" theme did not reach the lock screen: its background ($want) is nowhere in the generated config"
    fi
fi

printf 'lock screen theme contract: PASS\n'
