#!/bin/bash
set -eu
### --help Info: Утилита для создания и очистики бекапов баз данных
### --help Usage: /opt/bin/pg_backup backup|cleanup
### --help Example: /opt/bin/pg_backup backup

. /opt/fox_utils/crab_sys.sh

if [ "${1:---help}" = "--help" ]; then
	sys::usage "$@"
fi

sys::arg_parse "$@"

declare -A BACKUP_DIRS
BACKUP_DIRS["evadb"]="/opt/eva-app/backup"
declare CMD="$ARG_1"

[[ -f /opt/CONFIG ]] && . /opt/CONFIG
declare POSTGRESQL_ENABLED

db_list() {
	set -e
	echo evadb
	return 0
}

do_backup() {
	local db backup_name backup_dir tmp_backup_name
	for db in $(db_list); do
		if [ -v ARG_2 ]; then
			backup_name="${db}_backup.${ARG_2}"
		else
			backup_name="${db}_backup.$(date +%Y.%m.%d_%H.%M.%S)"
		fi
		tmp_backup_name="tmp__${backup_name}"
		backup_dir="${BACKUP_DIRS[$db]}"
		mkdir -p "$backup_dir"
		echo "Start backup $db"
		if pg_dump -U postgres -Fc -f "$backup_dir/$tmp_backup_name" "$db"; then
			mv "$backup_dir/$tmp_backup_name" "$backup_dir/$backup_name"
			ln -sf "$backup_dir/$backup_name" "$backup_dir/${db}_backup.latest"
			echo "Success backup $backup_dir/$backup_name"
		else
			echo "Error backup $db"
		fi
	done
	return 0
}

do_cleanup() {
	# Переходим на схему 1 бекап в день и храним 10 бекапов
	local keep_days=10 keep_now find_params
	for db in $(db_list); do
		backup_dir="${BACKUP_DIRS[$db]}"
		find_params="-type f -name "${db}_backup.*" -mtime -$((keep_days+1))"
		keep_now="$(find -H "$backup_dir" $find_params | wc -l)"
		[ "$keep_now" -ge "$keep_days" ] && keep_now="$keep_days"
		find -H "$backup_dir" -type f -name "${db}_backup.*" -mtime +$keep_days \
			| sort | head -n -$((keep_days-keep_now)) | xargs -r rm -vf
	done
	return 0

	local day week month offset
	local keep_hourly_days=2
	local keep_weekly_weeks=15
	local keep_monthly_month=8
	local keep_daily_days
	local db backup_dir backup_daily_dir backup_weekly_dir backup_monthly_dir
	for db in $(db_list); do
		backup_dir="${BACKUP_DIRS[$db]}"
		backup_daily_dir="$backup_dir/daily/"
		mkdir -p "$backup_daily_dir"
		# 2 дня мы храним бэкапы за каждый час (просто не удаляем);
		keep_daily_days="$((30 + keep_hourly_days))"
		# Следующие 30 дней (1 месяц) мы храним 1 бэкап за каждый день;
		for day in $(seq "$keep_hourly_days" "$keep_daily_days"); do
			# sort | tail -n +2 = удаляем все, кроме первого утреннего бэкапа
			# Ну или не утреннего если запустим скрипт не в полночь.
			# В принципе при расчистке запылившихся бэкапов не сильно важно
			find "$backup_dir" -type f -name "${db}_backup.*" \
				-mtime "$day" \
				| sort | tail -n +2 | xargs -r rm -vf
		done
		find "$backup_dir" -type f -name "${db}_backup.*" \
			-mtime +$keep_hourly_days \
			-mtime -$((keep_daily_days + 1)) \
			| sort | xargs -I {} mv -n {} "$backup_daily_dir"
		# Следующие 15 недель (почти 3 месяца) мы храним 1 бэкап за каждую неделю;
		backup_weekly_dir="$backup_dir/weekly/"
		mkdir -p "$backup_weekly_dir"
		offset=$((keep_daily_days - 7))
		for week in $(seq 1 "$keep_weekly_weeks"); do
			find "$backup_dir" -type f -name "${db}_backup.*" \
				-mtime +$((offset + week * 7)) \
				-mtime -$((offset + (week + 1) * 7 + 1)) \
				| sort | tail -n +2 | xargs -r rm -vf
		done
		find "$backup_dir" -type f -name "${db}_backup.*" \
			-mtime +$((offset + 7)) \
			-mtime -$((offset + (keep_weekly_weeks + 1) * 7)) \
			| sort | xargs -I {} mv -n {} "$backup_weekly_dir"
		# Следующие 8 месяцев мы храним 1 бэкап за каждый месяц.
		backup_monthly_dir="$backup_dir/monthly/"
		mkdir -p "$backup_monthly_dir"
		offset=$((keep_daily_days + keep_weekly_weeks * 7 - 30))
		for month in $(seq 1 "$keep_monthly_month"); do
			find "$backup_dir" -type f -name "${db}_backup.*" \
				-mtime +$((offset + month * 30)) \
				-mtime -$((offset + (month + 1) * 30 + 1)) \
				| sort | tail -n +2 | xargs -r rm -vf
		done
		find "$backup_dir" -type f -name "${db}_backup.*" \
			-mtime +$((offset + 30)) \
			-mtime -$((offset + (keep_monthly_month + 1) * 30)) \
			| sort | xargs -I {} mv -n {} "$backup_monthly_dir"
		# Удалим старше 8 месяцев
		offset=$((keep_daily_days + keep_weekly_weeks * 7 + keep_monthly_month * 30))
		find "$backup_dir" -type f -name "${db}_backup.*" \
			-mtime +$offset | sort | xargs -r rm -vf
	done
	return 0
}

main() {
	if [[ "${POSTGRESQL_ENABLED:-TRUE}" != "TRUE" ]]; then
		return 0
	fi
	echo "Started $CMD $(date +"%Y-%m-%d %H:%M:%S")"
	"do_${CMD}"
	echo "Finished $CMD $(date +"%Y-%m-%d %H:%M:%S")"
	return 0
}

main "$@"

exit 0
