#!/bin/bash

confirm() {
	read -p "$1 ([y]es or [N]o): "
	case $(echo $REPLY | tr '[A-Z]' '[a-z]') in
	y | yes) echo "yes" ;;
	*) echo "no" ;;
	esac
}

synopsis() {
	echo "usage: "
	printf "\t list | console | connections\n"
	printf "\t ---------------------------\n"
	printf "\t use <DB_NAME>\n"
	printf "\t lookup <DB_NAME> <TERM>\n"
	printf "\t create <DB_NAME> [PASSWORD]\n"
	printf "\t ---------------------------\n"
	printf "\t backup <DB_NAME> [FOLDER]\n"
	printf "\t restore <DB_NAME> <FILE> [--yes]\n"
	printf "\t ---------------------------\n"
	printf "\t rename <DB_NAME> <NEW_NAME>\n"
}

list() {
	lxc exec ct1 -- su - postgres -c "psql -Atc \"SELECT datname FROM pg_database WHERE datistemplate=false AND datname<>'postgres';\""
}

console() {
	if [[ -z $1 ]]; then
		lxc exec ct1 -- su - postgres
	else
		lxc exec ct1 -- su - postgres -c "$1"
	fi
}

connections() {
	PROCESSES=$(console "psql -c \"select pid as process_id, usename as username, datname as database_name, client_addr as client_address, application_name, backend_start, state, state_change from pg_stat_activity WHERE datname<>'postgres' ORDER BY datname, usename;\"")
	printf "$PROCESSES\n"
}

use() {
	echo >&2 "about to connect to <${DB_NAME}> ..."
	if [[ -z $1 ]]; then
		lxc exec ct1 -- su - postgres -c "psql $DB_NAME"
	else
		local sql="psql -A -t $DB_NAME -c \\\"$1;\\\""
		local command="su - postgres -c \"$sql\""
		lxc exec ct1 -- sh -c "$command"
	fi
}

create() {
	echo >&2 "about to create to <${DB_NAME}> ..."
	source /opt/miaou-bash/lib/functions.sh
	local DBs=($(list))
	if ! $(containsElement DBs $DB_NAME); then
		local SQL="CREATE USER \\\\\\\"$DB_NAME\\\\\\\" WITH PASSWORD '$DB_PASSWORD'"
		local command="su - postgres sh -c \"psql -c \\\"$SQL\\\"\" && su - postgres sh -c \"createdb -O $DB_NAME $DB_NAME\" && echo CREATE DB"
		# echo $command
		lxc exec ct1 -- sh -c "$command"
	else
		echo $DB_NAME already exists!
	fi

}

lookup() {
	if [[ ${#TERM} -ge 4 ]]; then
		echo >&2 "about to lookup term <${TERM}> over all tables of database <$DB_NAME> ..."
		local command="pg_dump --data-only --inserts $DB_NAME 2>/dev/null | grep --color \"$TERM\""
		lxc exec ct1 -- su - postgres -c "$command"
	else
		echo "term <$TERM> should contain 4 chars minimum!" && exit 2
	fi
}

backup() {
	if [[ ! -d "$FOLDER" ]]; then
		echo "error: Folder required!"
		file $FOLDER
		exit 2
	fi
	DATE=$(date '+%F')
	ARCHIVE="$FOLDER"/$DB_NAME-$DATE.postgres.gz

	if [[ -f $ARCHIVE ]]; then
		VERSION_CONTROL=numbered mv -b $ARCHIVE "$FOLDER"/$DB_NAME-$DATE-daily.postgres.gz
	fi

	echo "backup $DB_NAME $FOLDER"
	PGPASSWORD=$DB_NAME pg_dump -U $DB_NAME $DB_NAME -h ct1.lxd | gzip >"$ARCHIVE"
	echo "archive file created: $ARCHIVE"
}

restore() {
	echo "restore $DB_NAME $FILE"
	if [[ ! -f "$FILE" ]]; then
		echo "error: Backup file (*.postgres.gz) required!"
		file $FILE
		exit 2
	fi
	PROCESSES=$(console "psql -c \"select pid as process_id, usename as username, datname as database_name, client_addr as client_address, application_name, backend_start, state, state_change from pg_stat_activity WHERE datname='$DB_NAME';\"")
	PROCESS_COUNT=$(echo "$PROCESSES" | wc -l)
	if [[ $PROCESS_COUNT -gt 3 ]]; then
		echo "FAILURE: There are some connections to database, please consider stopping bound services"
		echo
		printf "$PROCESSES\n"
		exit 2
	fi

	if [[ $YES == "true" || "yes" == $(confirm "RESTORATION will drop DATABASE, please acknowledge with care!!!") ]]; then
		FOLDER="$HOME/RECOVERY_POSTGRES"
		mkdir -p "$FOLDER"
		backup
		echo "backup successful, now drop and restore"
		lxc exec ct1 -- su - postgres -c "dropdb $DB_NAME && createdb -O $DB_NAME $DB_NAME"
		gunzip -c "$FILE" | grep -v "^CREATE DATABASE" | PGPASSWORD=$DB_NAME PGOPTIONS='--client-min-messages=warning' psql -X -q -1 -v ON_ERROR_STOP=1 --pset pager=off -U $DB_NAME -h ct1.lxd $DB_NAME 2>&1 >/dev/null
	else
		exit 1
	fi
}

rename() {
	echo "rename <$DB_NAME> to <$DB_NEW_NAME>"
	mapfile -t LIST <<<"$(list)"
	found=false
	for db in "${LIST[@]}"; do
		[[ "$db" == "$DB_NEW_NAME" ]] && echoerr "destination database <$DB_NEW_NAME> already exists! Please provide another name." && exit 11
		[[ "$db" == "$DB_NAME" ]] && found=true
	done
	$found || (echoerr "source database <$DB_NAME> not found!" && exit 12)

	console "psql -c \"ALTER DATABASE \\\"$DB_NAME\\\" RENAME TO \\\"$DB_NEW_NAME\\\" \""
	console "psql -c \"ALTER USER \\\"$DB_NAME\\\" RENAME TO \\\"$DB_NEW_NAME\\\" \""
	console "psql -c \"ALTER USER \\\"$DB_NEW_NAME\\\" PASSWORD '$DB_NEW_NAME' \""

}

# MAIN
. "$MIAOU_BASEDIR/lib/init.sh"

[[ $# -lt 1 ]] && synopsis && exit 1
ACTION=$1

case $ACTION in
console)
	shift
	TAIL="$@"
	console "$TAIL"
	;;
list)
	list
	;;
connections)
	connections
	;;
use)
	[[ $# -lt 2 ]] && synopsis && exit 1
	DB_NAME=$2
	shift 2
	TAIL="$@"
	use "$TAIL"
	;;
create)
	[[ $# -lt 2 ]] && synopsis && exit 1
	DB_NAME=$2
	DB_PASSWORD=${3:-$DB_NAME}
	create
	;;
lookup)
	[[ $# -lt 3 ]] && synopsis && exit 1
	DB_NAME=$2
	TERM=$3
	lookup
	;;
backup)
	[[ $# -lt 2 ]] && synopsis && exit 1
	DB_NAME=$2
	FOLDER=${3:-.}
	backup
	;;
restore)
	[[ $# -lt 3 ]] && synopsis && exit 1
	DB_NAME=$2
	FILE=$3
	YES=true
	restore
	;;
rename)
	[[ $# -lt 3 ]] && synopsis && exit 1
	DB_NAME=$2
	DB_NEW_NAME=$3
	rename
	;;
*)
	synopsis
	exit 1
	;;
esac