#! /usr/bin/env bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
USER_HOME=$HOME
[[ -n "${SUDO_USER}" ]] && USER_HOME="$(eval "echo ~${SUDO_USER}")"
. ${SHRC_D:-$SCRIPT_DIR}/01_util.functions 

set -e

JSON=0
if [[ $# -gt 0 && "$1" =~ ^-- ]]; then
    if [[ "$1" == "--help" ]]; then
        cat <<USAGE
Usage:
       ./$(basename $0) --help
  sudo ./$(basename $0) <pvc-search-pattern>
  sudo ./$(basename $0) <pvc-name> <restore-from> [<tmp-dest>]

NOTE:
  DBG=' ' will add debug output
  without ZFS_DO=' ' zfs operations will not happen.

Description:
  <pvc-search-pattern>
      a simple match pattern, that will list any matching pvc names

  <pvc-name>
      Must match a unique pvc name, most commonly these are
      <app-name>-config or <app-name>-data.

  <restore-from>
      zfs path to the dataset contianing the restore data

  <tmp-dest> (optional)
      default value for this is:
        \${ZFS_POOL\}/backup/tmp-\${APP_NAME\}-\${PVC\}

      available variables are:
        NAME,APP_NAME,PVC,ZFS_POOL

Examples:

  List all PVCs ending with either '-data' or '-config':
      sudo ./$(basename $0) '-(data|config)$'

  Replace gitea-data's pvc with the one stored in tank/backup/gitea/pvc-backup
  preserving the current gitea-data pvc in the default location:
  tank/backup/tmp-gitea-data-pvc-... :
      sudo ./$(basename $0) 'gitea-data' 'tank/backup/gitea/pvc-backup'
      
USAGE
        exit 0
    elif [[ "$1" == "--json" ]]; then
        JSON=1
    fi
    shift
fi

require_root

PVCS="$(
    k3s kubectl get persistentvolume --output json \
    | jq  '
        .items[]
        | select( .spec.claimRef.name | test("'"${1}"'") )
        | {
            name: .spec.claimRef.name
           ,app: .spec.claimRef.namespace | sub("ix-"; "")
           ,pvc: .spec.csi.volumeHandle
           ,zfs_pvc: "\(
                    .spec.csi.volumeAttributes."openebs.io/poolname"
                )/\(
                    .spec.csi.volumeHandle
                )"
           ,zfs_pool:
                .spec.csi.volumeAttributes."openebs.io/poolname"
                | split("/")[0]
           #,raw: .
        }
    '
)"

DISPLAY_ONLY=0
LEN="$(jq -s 'length' <<<"$PVCS")"
if [[ $# -eq 1 || "$LEN" -ne 1 ]]; then
    DISPLAY_ONLY=1
fi
if [[ "$LEN" -eq 0 ]]; then
    PVCS='"ERROR: EMPTY query results"'
fi
if [[ "${DISPLAY_ONLY}" != 0 ]]; then
    jq -r <<<"$PVCS"
    exit 0
fi

ENV="$(
    <<<"$PVCS" jq -r "[
        \"NAME='\(.name)'\" 
       ,\"APP_NAME='\(.app)'\"
       ,\"PVC='\(.pvc)'\" 
       ,\"ZFS_PVC='\(.zfs_pvc)'\"
       ,\"ZFS_POOL='\(.zfs_pool)'\"
       ] | join (\"\n\")
    "
)"
${DBG:-:} echo "$ENV" 1>&2
eval $ENV

TMP_DEST="${3:-\${ZFS_POOL\}/backup/tmp-\${APP_NAME\}-\${PVC\}}"
${DBG:-:} echo "$TMP_DEST" 1>&2
eval "TMP_DEST=\"${TMP_DEST}\""
${DBG:-:} echo "$TMP_DEST" 1>&2

if [[ -z "$(type -fp zfs)" ]]; then
    printf "ERROR: zfs is not a valid command (is your PATH correct?)\n" 1>&2
    exit 2
fi

VALIDATE=()
zfs list -Ho name "$ZFS_PVC" >/dev/null 2>&1 || VALIDATE=( "${VALIDATE[@]}"
    "ZFS_PVC '$ZFS_PVC' cannot be found")
zfs list -Ho name "${2}" >/dev/null 2>&1 || VALIDATE=( "${VALIDATE[@]}"
    "Restore source '${2}' cannot be found") || true
zfs list -Ho name "${TMP_DEST%/*}" >/dev/null 2>&1 || VALIDATE=( "${VALIDATE[@]}"
    "Parent of temp-dset '${TMP_DEST%/*}' cannot be found")
zfs list -Ho name "$TMP_DEST" >/dev/null 2>&1 && VALIDATE=( "${VALIDATE[@]}"
    "Temp dest '${TMP_DEST}' already exists") || true

if [[ ${#VALIDATE[@]} -ne 0 ]]; then
    ${DBG:-:} echo "" 1>&2 
    printf 'ERROR: %s\n' "${VALIDATE[@]}" 1>&2 
    exit 1
fi

printf '%s\n' \
    "Performing the following actions:" \
    "  zfs rename '$ZFS_PVC' '${TMP_DEST}'" \
    "  zfs rename '${2}' '$ZFS_PVC'" \
    '' '' \
    'To revert these changes manualy run:' \
    "  sudo zfs rename '$ZFS_PVC' '${2}' " \
    "  sudo zfs rename '${TMP_DEST}' '$ZFS_PVC' " \
    '' ''

${ZFS_DO:-:} zfs rename "$ZFS_PVC" "${TMP_DEST}"
${ZFS_DO:-:} zfs rename "${2}" "$ZFS_PVC"