#!/bin/bash
set -eE

BACKUPFILE="$1"

DBADMIN=ncadmin
DBPASSWD="$( grep password /root/.my.cnf | sed 's|password=||' )"

source /usr/local/etc/library.sh # sets PHPVER

DIR="$( cd "$( dirname "$BACKUPFILE" )" &>/dev/null && pwd )" #abspath

[[ -f /.docker-image ]] && NCDIR=/data/nextcloud || NCDIR=/var/www/nextcloud

[[ $# -eq 0           ]] && { echo "missing first argument"         ; exit 1; }
[[ -f "$BACKUPFILE"   ]] || { echo "$BACKUPFILE not found"          ; exit 1; }
[[ "$DIR" =~ "$NCDIR".* ]] && { echo "Refusing to restore from $NCDIR"; exit 1; }

TEMPDIR="$( mktemp -d "$( dirname "$BACKUPFILE" )"/ncp-restore.XXXXXX )" || { echo "Failed to create temp dir" >&2; exit 1; }
[[ "$(stat -fc%T "${TEMPDIR}")" =~ ext|btrfs|zfs ]] || { echo "Can only restore from ext/btrfs/zfs filesystems (found '$(stat -fc%T "${TEMPDIR}")"     >&2; exit 1; }

TEMPDIR="$( cd "$TEMPDIR" &>/dev/null && pwd )" || { echo "$TEMPDIR not found"; exit 1; } #abspath
cleanup(){  local RET=$?; echo "Cleanup..."; rm -rf "${TEMPDIR}"; trap "" EXIT; exit $RET; }
trap cleanup INT TERM HUP ERR EXIT
rm -rf "$TEMPDIR" && mkdir -p "$TEMPDIR"

[[ "$BACKUPFILE" =~ .*".tar.gz" ]] && compress_arg="-I pigz"

# CHECK FREE SPACE IN $TEMPDIR
echo "check free space..." # allow at least ~100 extra MiB
extractedsize=$(tar $compress_arg -tvf "$BACKUPFILE" | awk '{s+=$3} END{printf "%.0f", (s/1024)}') # Size of extracted files in "KB"
size=$(($extractedsize + 100*1024))
free=$( df "$TEMPDIR" | tail -1 | awk '{ print $4 }' )
[ $size -ge $free ] && {
  echo "free space check failed. Need $size KB in $TEMPDIR";
  exit 1;
}

# EXTRACT FILES
echo "extracting backup file $BACKUPFILE..."
tar $compress_arg -xf "$BACKUPFILE" -C "$TEMPDIR" || exit 1

## SANITY CHECKS
[[ -d "$TEMPDIR"/nextcloud ]] && [[ -f "$( ls "$TEMPDIR"/nextcloud-sqlbkp_*.bak 2>/dev/null )" ]] || {
  echo "invalid backup file. Abort"
  exit 1
}

## RESTORE FILES

echo "restore files..."
[[ -d "$NCDIR/data" ]] && {
  DATA_BKP_DIR="$(mktemp -d -p "$NCDIR/.." nc-data-XXXXXX)"
  mv -T "$NCDIR/data" "$DATA_BKP_DIR/"
}
rm -rf "$NCDIR"
mv -T "$TEMPDIR"/nextcloud "$NCDIR" || { echo "Error restoring base files"; exit 1; }

if [[ -n "$DATA_BKP_DIR" ]]
then
  target="$NCDIR/data"
  [[ -d "$target" ]] && {
    target="$NCDIR/.data_$(date '+%FT%s')"
    echo "DATA CONFLICT! Your old '$NCDIR/data' directory can be found in '$target' after the restore script is done. The new '$NCDIR/data' directory will be restored from the backup. You can manually merge these directories with this command (run nc-fix-permissions and nc-scan afterwards): cp -rn '$target/'* '$target/'.[!.]* '$NCDIR/data/'"
  }
  echo "Restoring old '$NCDIR/data' to '$target'..."
  mv -T "$DATA_BKP_DIR" "$target"
fi

# update NC database password to this instance
sed -i "s|'dbpassword' =>.*|'dbpassword' => '$DBPASSWD',|" /var/www/nextcloud/config/config.php

# update redis credentials
REDISPASS="$( grep "^requirepass" /etc/redis/redis.conf | cut -f2 -d' ' )"
[[ "$REDISPASS" != "" ]] && \
  sed -i "s|'password'.*|'password' => '$REDISPASS',|" /var/www/nextcloud/config/config.php
service redis-server restart

## RE-CREATE DATABASE TABLE

echo "restore database..."
mysql -u root <<EOFMYSQL
DROP DATABASE IF EXISTS nextcloud;
CREATE DATABASE nextcloud;
GRANT USAGE ON *.* TO '$DBADMIN'@'localhost' IDENTIFIED BY '$DBPASSWD';
DROP USER '$DBADMIN'@'localhost';
CREATE USER '$DBADMIN'@'localhost' IDENTIFIED BY '$DBPASSWD';
GRANT ALL PRIVILEGES ON nextcloud.* TO $DBADMIN@localhost;
EXIT
EOFMYSQL
# shellcheck disable=SC2181
[ $? -ne 0 ] && { echo "Error configuring nextcloud database"; exit 1; }

mysql -u root nextcloud <  "$TEMPDIR"/nextcloud-sqlbkp_*.bak || { echo "Error restoring nextcloud database"; exit 1; }

## RESTORE DATADIR

DATADIR="$(get_nc_config_value datadirectory)"
if is_docker && [[ "$DATADIR" == "/var/www/nextcloud/data" ]]; then
  DATADIR=/data/nextcloud/data
fi
[[ "$DATADIR" == "" ]] && { echo "Error reading data directory"; exit 1; }

cd "$NCDIR"

### INCLUDEDATA=yes situation
NUMFILES=2
if [[ $( ls "$TEMPDIR" | wc -l ) -eq $NUMFILES ]]; then

  [[ -e "$DATADIR" ]] && {
    bk_target="$DATADIR-$( date '+%FT%s' )"
    echo "backing up existing $DATADIR to ${bk_target}..."
    mv "$DATADIR" "${bk_target}" || exit 1
  }

  echo "restore datadir to $DATADIR..."

  mkdir -p "$DATADIR"
  grep -q "btrfs" <(stat -fc%T "$DATADIR") && which btrfs &>/dev/null && {
    rmdir "$DATADIR"                  || exit 1
    btrfs subvolume create "$DATADIR" || exit 1
  }
  chown www-data: "$DATADIR"
  TMPDATA="$TEMPDIR/$( basename "$DATADIR" )"
  mv "$TMPDATA"/* "$TMPDATA"/.[!.]* "$DATADIR" || exit 1
  rmdir "$TMPDATA"                             || exit 1

  ncc maintenance:mode --off

### INCLUDEDATA=no situation

else
  echo "No datadir found in backup"

  [[ -e "$DATADIR" ]] || {
    echo -n "${DATADIR} not found."
    DATADIR="/data/ncdata/data"
    is_docker || DATADIR="/opt/data"
    echo "Resetting to ${DATADIR}"
    mkdir -p "${DATADIR}"
    touch "${DATADIR}"/.ocdata
    chown -R www-data: "${DATADIR}"
  }

  ncc maintenance:mode --off
  ncc files:scan --all

  # cache needs to be cleaned as of NC 12
  NEED_RESTART=1
fi

sed -i "s|'datadirectory' =>.*|'datadirectory' => '${DATADIR}',|" "${NCDIR}"/config/config.php

# Just in case we moved the opcache dir
install_template "php/opcache.ini.sh" "/etc/php/${PHPVER}/mods-available/opcache.ini"

# tmp upload dir
mkdir -p "$DATADIR/tmp"
chown www-data: "$DATADIR/tmp"
ncc config:system:set tempdirectory --value "$DATADIR/tmp"
sed -i "s|^;\?upload_tmp_dir =.*$|upload_tmp_dir = $DATADIR/tmp|" "/etc/php/${PHPVER}/cli/php.ini"
sed -i "s|^;\?upload_tmp_dir =.*$|upload_tmp_dir = $DATADIR/tmp|" "/etc/php/${PHPVER}/fpm/php.ini"
sed -i "s|^;\?sys_temp_dir =.*$|sys_temp_dir = $DATADIR/tmp|"     "/etc/php/${PHPVER}/fpm/php.ini"

# logs
ncc config:system:set logfile --value="$DATADIR/nextcloud.log"

# update fail2ban logpath
[[ -f /etc/fail2ban/jail.conf ]] && {
  sed -i "s|logpath  =.*|logpath  = $DATADIR/nextcloud.log|" /etc/fail2ban/jail.conf
  pgrep fail2ban &>/dev/null && service fail2ban restart
}

# refresh nextcloud trusted domains
bash /usr/local/bin/nextcloud-domain.sh

# update the systems data-fingerprint
ncc maintenance:data-fingerprint

# refresh thumbnails
ncc files:scan-app-data

# restart PHP if needed
[[ "$NEED_RESTART" == "1" ]] && {
  bash -c "sleep 5; source /usr/local/etc/library.sh; clear_opcache; service php${PHPVER}-fpm restart" &>/dev/null &
}
