#!/usr/bin/env bash
#
# omv-microvm-sync-backups-list — reconcile /etc/omv-microvm-backup.list
# against what actually exists on disk.
#
# A list row is valid if <path>/<vmname>/<date>/rootfs.ext4 still exists.
# Anything else is an orphan — typically left behind when a backup's
# retention (-k) pruned the directory but the list file wasn't updated
# for some other reason (a crashed run, a manual rm, files copied/removed
# outside the plugin) — and is dropped. This only removes rows; it does
# not add rows for backup directories found on disk but missing from the
# list, since there's no reliable way to recover their vmname/date from
# an arbitrary directory layout.
#
# Usage: omv-microvm-sync-backups-list [-v vmname] [-d path]

set -uo pipefail

if [[ $(id -u) -ne 0 ]]; then
    echo "This script must be executed as root or using sudo."
    exit 99
fi

export LC_ALL=C.UTF-8

logFile="/var/log/omv-microvm-backup.log"
listFile="/etc/omv-microvm-backup.list"

syncVm=""
syncPath=""

_log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S%z')] [sync] ${1}" | tee -a "${logFile}" >&2
}

while getopts "d:hv:" opt; do
    case "${opt}" in
        d)
            syncPath="${OPTARG}"
            ;;
        h)
            echo "Usage: omv-microvm-sync-backups-list [-v vmname] [-d path]"
            echo "  Reconcile the backup list file against what actually exists on disk,"
            echo "  dropping rows whose backup directory is gone."
            echo ""
            echo "  -v vmname    limit to a single VM"
            echo "  -d path      limit to a single VM's backup path (used with -v)"
            echo "  -h           this help text"
            exit 0
            ;;
        v)
            syncVm="${OPTARG}"
            ;;
        *)
            echo "Invalid option: -${OPTARG}"
            exit 1
            ;;
    esac
done

if [ ! -f "${listFile}" ]; then
    _log "No list file at '${listFile}', nothing to sync."
    exit 0
fi

backupFile="${listFile}.bak"
cp -a "${listFile}" "${backupFile}"
_log "Backed up '${listFile}' to '${backupFile}'"

tmpFile=$(mktemp)
trap 'rm -f "${tmpFile}"' EXIT

declare -i scanned=0
declare -i kept=0
declare -i removed=0

while IFS=, read -r uuid path vmname date used; do
    [ -z "${uuid}" ] && continue
    scanned+=1

    if [ -n "${syncVm}" ] && [ "${vmname}" != "${syncVm}" ]; then
        echo "${uuid},${path},${vmname},${date},${used}" >> "${tmpFile}"
        kept+=1
        continue
    fi
    if [ -n "${syncPath}" ] && [ "${path%/}" != "${syncPath%/}" ]; then
        echo "${uuid},${path},${vmname},${date},${used}" >> "${tmpFile}"
        kept+=1
        continue
    fi

    if [ -f "${path%/}/${vmname}/${date}/rootfs.ext4" ]; then
        echo "${uuid},${path},${vmname},${date},${used}" >> "${tmpFile}"
        kept+=1
    else
        _log "Removing orphaned entry :: ${vmname} ${date} (${path})"
        removed+=1
    fi
done < "${listFile}"

mv "${tmpFile}" "${listFile}"
trap - EXIT

_log "Synced list file :: scanned ${scanned}, kept ${kept}, removed ${removed}"
