#!/bin/bash

set -e

. "${INSTALLER_DIR}/wizard"

ADDON_VERSION="v1"

MSG_CONFLICTING_INSTALL="ERROR: It seems like you already have PostgreSQL installed. Please run '$APP_NAME reconfigure' and choose to use the existing installation instead."
MSG_UNKNOWN_DISTRIBUTION_VERSION="ERROR: The current distribution is not supported by this wizard. Please install PostgreSQL manually and retry."
MSG_CONNECTION_KO="ERROR: Connection KO. Aborting postgres installation. You should check the wizard configuration in /etc/$APP_NAME/installer.dat"

PGHOST="$(wiz_get "postgres/db_host" || echo "127.0.0.1")"
PGPORT="$(wiz_get "postgres/db_port" || echo "5432")"
PGDATABASE="$(wiz_get "postgres/db_name" || echo "$APP_SAFE_NAME")"
PGUSER="$(wiz_get "postgres/db_username" || echo "$APP_SAFE_NAME")"
PGPASSWORD="$(wiz_get "postgres/db_password" || echo "")"

CONF_FILE="/etc/${APP_NAME}/conf.d/00_addon_postgres"

install_postgres_server() {
	case $(wiz_fact "osfamily") in
		"debian")
			case $(wiz_fact "osversion") in
				"7")
					codename="wheezy"
					;;
				"8")
					codename="jessie"
					;;
				"9")
					codename="stretch"
					;;
				"10")
					codename="buster"
					;;
				"11")
					codename="bullseye"
					;;
				"12")
					codename="bookworm"
					;;
				"14.04")
					codename="trusty"
					;;
				"16.04")
					codename="xenial"
					;;
				"18.04")
					codename="bionic"
					;;
				"20.04")
					codename="focal"
					;;
				"22.04")
					codename="jammy"
					;;
			esac

		if [ "$codename" != "" ]; then
			if ! wiz_check_package "postgresql-17" ; then
				_ensure_port_available
				echo "deb https://apt.postgresql.org/pub/repos/apt/ ${codename}-pgdg main" > /etc/apt/sources.list.d/pgdg.list
				echo -n "INFO: Adding repository signing key from PostgreSQL... "
				wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
				echo "INFO: Installing PostgreSQL v17..."
				apt-get update -qq
				DEBIAN_FRONTEND=noninteractive apt-get install postgresql-17 -y

				su - postgres -c "/usr/lib/postgresql/17/bin/pg_ctl -D /var/lib/postgresql/17/main -w -t 10 stop || true"
				_configure_postgres_server "/etc/postgresql/17/main"
				sleep 3
				su - postgres -c "/usr/lib/postgresql/17/bin/pg_ctl -D /var/lib/postgresql/17/main -w -t 10 -l logfile restart"
			else
				_error_if_conflicting_install
			fi
			_configure_database_and_user
			else
				echo "$MSG_UNKNOWN_DISTRIBUTION_VERSION"
				exit 1
			fi
			;;
		"redhat")
			case $(wiz_fact "osversion") in
				7*)
					repo="https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm"
					;;
				8*)
					repo="https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm"
					dnf -qy module disable postgresql
					;;
				9*)
					repo="http://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm"
					dnf -qy module disable postgresql
					;;
				*)
					echo "$MSG_UNKNOWN_DISTRIBUTION_VERSION"
					exit 1
					;;
			esac

		if ! wiz_check_package "postgresql17-server" ; then
			_ensure_port_available
			echo "INFO: Installing PostgreSQL v17..."
			yum install -y "$repo"
			yum install -y postgresql17-server postgresql17 postgresql17-contrib
			PGSETUP_INITDB_OPTIONS="--auth-local peer --auth-host md5" /usr/pgsql-17/bin/postgresql-17-setup initdb

			_configure_postgres_server "/var/lib/pgsql/17/data"
			wiz_service_enable postgresql-17
			wiz_service_restart postgresql-17
		else
			_error_if_conflicting_install
		fi
			_configure_database_and_user

			;;
		"suse")
			echo "$MSG_UNKNOWN_DISTRIBUTION_VERSION"
			exit 1
			;;
	esac
}

function _error_if_conflicting_install() {
	local addon_version="$(wiz_get "postgres/addon_version" || echo "v0")"

	if [ "$addon_version" == "$ADDON_VERSION" ]; then
		echo "INFO: PostgreSQL server has already been configured by this addon."
	else
		echo "$MSG_CONFLICTING_INSTALL"
		exit 1
	fi
}

function _ensure_connection_ok() {
	echo -n "INFO: Checking connection to PostgreSQL server... "
	if env -i PATH="$PATH" PGCONNECT_TIMEOUT=5 PGPORT="$PGPORT" PGHOST="$PGHOST" PGDATABASE="$PGDATABASE" PGUSER="$PGUSER" PGPASSWORD="$PGPASSWORD" \
		psql --no-readline --no-password -c "select 1;" ; then
		echo "OK"
	else
		echo "KO"
		echo "$MSG_CONNECTION_KO"
		exit 1
	fi
}

function _ensure_port_available() {
	echo -n "INFO: Checking whether port $PGPORT is available... "
	# assume port is free if netstat unavailable
	if ! which netstat &>/dev/null ; then
		echo "OK (netstat not found)"
		return 0;
	fi

	if netstat -tulpn | grep ":$PGPORT" &>/dev/null ; then
		echo "KO"
		echo "ERROR: port $PGPORT is already in use. Can't install new PostgreSQL server."
		exit 1
	else
		echo "OK"
		return 0
	fi
}

function _configure_postgres_server() {
	local base_dir="$1"
	sed -i "s|^#include_dir = .*|include_dir = 'conf.d'|" $base_dir/postgresql.conf
	mkdir -p $base_dir/conf.d
	echo "port = $PGPORT" > $base_dir/conf.d/custom.conf
	chown -R postgres:postgres $base_dir/conf.d
}

function _configure_database_and_user() {
	if su - postgres -c "createuser -p $PGPORT --createdb --login --superuser $PGUSER 2>&1 || true" | grep -q "already exists" ; then
		echo "INFO: user $PGUSER already exists"
	fi
	su - postgres -c "psql -p $PGPORT --no-readline --no-password -c \"alter user $PGUSER with encrypted password '$PGPASSWORD';\""

	if su - postgres -c "createdb -p $PGPORT -O $PGUSER $PGDATABASE 2>&1 || true" | grep -q "already exists" ; then
		echo "INFO: database $PGDATABASE already exists"
	fi
}

case "$(wiz_get "postgres/autoinstall")" in
	"skip")
		echo "INFO: autoinstall=skip. Skipping to next step."
		;;
	"install")
		echo "INFO: autoinstall=install. A new PostgreSQL v17 server will be installed locally unless a conflicting installation is found."
		if [ -f "$CONF_FILE" ]; then
			echo "INFO: existing installation found. Skipping to next step."
			_ensure_connection_ok
		else
			install_postgres_server
			wiz_set "postgres/addon_version" "$ADDON_VERSION"
			_ensure_connection_ok
		fi
		;;
	"reuse")
		echo "INFO: autoinstall=reuse. Skipping to next step."
		;;
	*)
		echo "ERROR: Unknown value for postgres/autoinstall"
		exit 1
		;;
esac

exit 0
