#!/usr/bin/env bash
set -euo pipefail

readonly snapshot_mount='/.snapshots'
readonly snapshot_dir='/.snapshots/portage'
readonly keep_count=32
readonly minimum_free_bytes=2147483648

warn() {
    printf 'portage-btrfs-snapshot: %s\n' "$*" >&2
}

fail() {
    warn "$*"
    exit 1
}

[[ ${EUID} -eq 0 ]] || fail 'must run as root from a Portage package phase.'
[[ $# -eq 5 ]] || fail 'usage: portage-btrfs-snapshot {install|remove} CATEGORY PF ROOT EROOT'

operation=$1
category=$2
package_pf=$3
target_root=$4
effective_root=$5
case "$operation" in
    install|remove) ;;
    *) fail 'unsupported package operation.' ;;
esac

# Restrict this hook to merges for the live root. Do not snapshot a prefix or
# alternate ROOT that happens to share the same Portage configuration.
[[ "$target_root" == / && "$effective_root" == / ]] || exit 0

for tool in awk btrfs date df find findmnt head install mountpoint python3 sed sort tr; do
    command -v "$tool" >/dev/null 2>&1 || fail "required command not found: $tool"
done

[[ $(findmnt -n -o FSTYPE --target /) == btrfs ]] || fail 'the active root is not Btrfs.'
mountpoint -q -- "$snapshot_mount" || fail "$snapshot_mount is not a mounted filesystem."
[[ $(findmnt -n -o FSTYPE --mountpoint "$snapshot_mount") == btrfs ]] || \
    fail "$snapshot_mount is not a Btrfs mountpoint."

root_uuid=$(btrfs filesystem show / 2>/dev/null | sed -n 's/.*uuid: \([^[:space:]]*\).*/\1/p' | head -n 1)
snap_uuid=$(btrfs filesystem show "$snapshot_mount" 2>/dev/null | sed -n 's/.*uuid: \([^[:space:]]*\).*/\1/p' | head -n 1)
[[ -n "$root_uuid" && "$root_uuid" == "$snap_uuid" ]] || \
    fail 'root and snapshot destination are not on the same Btrfs filesystem.'

root_id=$(btrfs inspect-internal rootid / 2>/dev/null) || fail 'cannot identify the root subvolume.'
dest_id=$(btrfs inspect-internal rootid "$snapshot_mount" 2>/dev/null) || \
    fail 'cannot identify the snapshot destination subvolume.'
[[ "$root_id" != "$dest_id" ]] || fail 'snapshot destination resolves to the live root subvolume.'

space_info=$(df -P -B1 "$snapshot_mount" | awk 'NR == 2 { print $2, $4 }') || \
    fail 'cannot determine free space on the Btrfs filesystem.'
read -r _total_bytes available_bytes <<< "$space_info"
[[ ${available_bytes:-} =~ ^[0-9]+$ ]] || fail 'cannot determine free space on the Btrfs filesystem.'
(( available_bytes >= minimum_free_bytes )) || \
    fail 'less than 2 GiB is available on Btrfs; refusing to create another snapshot.'

install -d -o root -g root -m 0700 -- "$snapshot_dir"

safe_package=$(printf '%s_%s' "$category" "$package_pf" | LC_ALL=C tr -c 'A-Za-z0-9._+-' '_')
timestamp=$(date -u +%Y%m%dT%H%M%S%N)
snapshot_path="${snapshot_dir}/portage-${timestamp}-${operation}-${safe_package}"

btrfs subvolume snapshot -r / "$snapshot_path" >/dev/null || \
    fail "snapshot creation failed for ${category}/${package_pf} (${operation})."
printf 'Created read-only Btrfs snapshot: %s\n' "$snapshot_path"

menu_manager='/usr/local/libexec/portage-limine-menu'
if [[ -x "$menu_manager" ]]; then
    if [[ "$operation" == install && "$category" == sys-kernel ]]; then
        # Kernel package post-install runs after its image has been installed.
        # Sync kernel groups and attach all compatible snapshots, including
        # the snapshot just created above.
        "$menu_manager" sync-kernels || \
            warn "Limine kernel/snapshot menu reconciliation failed after ${category}/${package_pf}."
    else
        "$menu_manager" add-snapshot "$snapshot_path" || \
            warn "Limine recovery entry creation failed for $snapshot_path."
    fi
else
    warn 'Limine menu manager is missing; the read-only snapshot was created without a boot entry.'
fi

# Names begin with a sortable UTC timestamp. Only remove our own snapshots,
# after confirming each candidate is an actual Btrfs subvolume.
mapfile -t snapshots < <(find "$snapshot_dir" -mindepth 1 -maxdepth 1 -type d \
    -name 'portage-*' -printf '%f\n' | LC_ALL=C sort)
excess=$((${#snapshots[@]} - keep_count))
if (( excess > 0 )); then
    for ((i = 0; i < excess; i++)); do
        old_path="${snapshot_dir}/${snapshots[i]}"
        if btrfs subvolume show "$old_path" >/dev/null 2>&1; then
            if [[ -x "$menu_manager" ]]; then
                "$menu_manager" remove-snapshot "$old_path" || {
                    warn "retention kept snapshot because its Limine entry/clone could not be removed: $old_path"
                    continue
                }
            fi
            btrfs subvolume delete "$old_path" >/dev/null || \
                warn "could not prune old snapshot: $old_path"
        else
            warn "retention skipped a non-subvolume entry: $old_path"
        fi
    done
fi
