#!/bin/bash

set -o pipefail

BACKUP_ROOT=/var/backups/mysql
PANEL_CONFIG=/var/www/system/htdocs/whfpanel/lib/userdata.inc.php
PHP_BIN=/usr/bin/php7.4

if [[ ! -x "$PHP_BIN" ]]; then
	PHP_BIN=$(command -v php)
fi

if [[ ! -r "$PANEL_CONFIG" ]]; then
	echo "Panel-Konfiguration ist nicht lesbar: $PANEL_CONFIG" >&2
	exit 1
fi

if [[ ! -d "$BACKUP_ROOT" ]]; then
	echo "Backup-Verzeichnis existiert nicht: $BACKUP_ROOT" >&2
	exit 1
fi

MYSQL_CNF=$(mktemp)
cleanup() {
	rm -f -- "$MYSQL_CNF"
}
trap cleanup EXIT HUP INT TERM
chmod 600 "$MYSQL_CNF"

if ! "$PHP_BIN" -r '
require $argv[1];
if (!isset($sql["root_user"], $sql["root_password"])) {
    fwrite(STDERR, "Root-Zugangsdaten fehlen.\n");
    exit(1);
}
$quote = function ($value) {
    return "\"" . str_replace(array("\\", "\""), array("\\\\", "\\\""), $value) . "\"";
};
$content = "[client]\nuser=" . $quote($sql["root_user"])
    . "\npassword=" . $quote($sql["root_password"]) . "\n";
if (file_put_contents($argv[2], $content) === false) {
    exit(1);
}
' "$PANEL_CONFIG" "$MYSQL_CNF"; then
	echo "Temporäre MySQL-Zugangskonfiguration konnte nicht erstellt werden." >&2
	exit 1
fi

shopt -s nullglob
backup_files=("$BACKUP_ROOT"/*/*.sql.gz)

if (( ${#backup_files[@]} == 0 )); then
	legacy_files=("$BACKUP_ROOT"/*/*.sql)
	if (( ${#legacy_files[@]} > 0 )); then
		echo "Es wurden nur alte, serverblinde SQL-Backups gefunden. Automatischer Restore wurde aus Sicherheitsgründen abgebrochen." >&2
		exit 1
	fi
	echo "Keine Backups gefunden."
	exit 0
fi

status=0

for backup_file in "${backup_files[@]}"; do
	filename=${backup_file##*/}

	if [[ ! $filename =~ ^db-([A-Za-z0-9._~%-]+)__server-([0-9]+)__host-([A-Za-z0-9._~-]+)__port-([0-9]+)__[0-9]{8}_[0-9]{6}\.sql\.gz$ ]]; then
		echo "Überspringe Datei mit unbekanntem Format: $backup_file" >&2
		status=1
		continue
	fi

	database_token=${BASH_REMATCH[1]}
	server_id=${BASH_REMATCH[2]}
	host_token=${BASH_REMATCH[3]}
	port=${BASH_REMATCH[4]}
	host=${host_token//~/:}

	if (( 10#$port < 1 || 10#$port > 65535 )); then
		echo "Überspringe Datei mit ungültigem Port: $backup_file" >&2
		status=1
		continue
	fi

	if ! server_config=$("$PHP_BIN" -r '
require $argv[1];
$id = (int)$argv[2];
if ((string)$id !== (string)$argv[2] || !isset($conf["mysql_server"][$id])) {
    exit(1);
}
$server = $conf["mysql_server"][$id];
if (!isset($server["host"], $server["port"])) {
    exit(1);
}
echo $server["host"] . "\t" . (int)$server["port"];
' "$PANEL_CONFIG" "$server_id"); then
		echo "Unbekannte Server-ID in Backup-Datei: $backup_file" >&2
		status=1
		continue
	fi
	IFS=$'\t' read -r configured_host configured_port <<< "$server_config"
	if [[ "$host" != "$configured_host" || "$port" != "$configured_port" ]]; then
		echo "Servermetadaten stimmen nicht mit der Konfiguration überein: $backup_file" >&2
		status=1
		continue
	fi

	echo "Stelle Datenbank $database_token aus $filename auf Server $server_id ($host:$port) wieder her ..."
	if ! gzip -cd -- "$backup_file" |
		mariadb --defaults-extra-file="$MYSQL_CNF" \
			--protocol=TCP --host="$host" --port="$port"
	then
		echo "Restore fehlgeschlagen: $backup_file" >&2
		status=1
	fi
done

exit "$status"
