#!/usr/bin/env bash
set -euo pipefail

APP_DATA_DIR="$(readlink -f $(dirname "${BASH_SOURCE[0]}")/..)"
DFWEBOS_ROOT="${APP_DATA_DIR}/../.."

CONFIG_PHP_FILE="${APP_DATA_DIR}/data/nextcloud/config/config.php"

APP_COMPOSE_FILE="${APP_DATA_DIR}/docker-compose.yml"
APP_COMPOSE_BACKUP_FILE="${APP_DATA_DIR}/docker-compose.yml.bak"

# Поддерживаемый список миграции основных версий Nextcloud
VERSIONS=()
VERSIONS+=( "22" )
VERSIONS+=( "23" )
VERSIONS+=( "24" )
VERSIONS+=( "25" )
VERSIONS+=( "26" )
VERSIONS+=( "27" )
VERSIONS+=( "28" )
VERSIONS+=( "29" )
VERSIONS+=( "30" )
VERSIONS+=( "31" )
VERSIONS+=( "32" )
VERSIONS+=( "33" )

# Список образов основных версий Nextcloud для миграции
IMAGES=()
IMAGES+=( "nextcloud:22.2.10-apache@sha256:71c4fb75d7c035ea2c840ebc1adf0da144b0c69e39ce925f4a2ea84b7c06db18" )
IMAGES+=( "nextcloud:23.0.11-apache@sha256:671ed70c7b204c63cb56d5c0d5dd624abec5eadeacd492191e65e834ddffef26" )
IMAGES+=( "nextcloud:24.0.7-apache@sha256:f95a21b598b7470b788251db5b0bbe9516992fdb865e7a8978980585e36eb715" )
IMAGES+=( "nextcloud:25.0.1-apache@sha256:a200319b132c01ec3486e0dcaf052092b560ec30ac9b78115607696dd201f704" )
IMAGES+=( "nextcloud:26.0.9-apache@sha256:23180fbe8169d428ce0058bfc8d47793628a16e00e40b495d82e4504a124b3fa" )
IMAGES+=( "nextcloud:27.0.2-apache@sha256:3c8040278bdc991cbc025278eaffc4978a9c2fd4ac34e95b10f646dcadb7c3fb" )
IMAGES+=( "nextcloud:28.0.3-apache@sha256:ed07f89119dcca2a3711897c48a8ac969542d96d69384445d8fcdc7804ca946f" )
IMAGES+=( "nextcloud:29.0.7-apache@sha256:3bcd2afa9d02fccc52251712bee1afc4f5891beaf353af47881b7662cd1308f7" )
IMAGES+=( "nextcloud:30.0.5-apache@sha256:02441f524c6fab3aadbf7157f6e0484927e231d685b248dc0734fa2941b4445e" )
IMAGES+=( "nextcloud:31.0.9-apache@sha256:11f158050216614d585886600445e0a1b75ee224d6a6dddc5eba996cc9499fa6" )
IMAGES+=( "nextcloud:32.0.6-apache@sha256:0e1084cc59df77bec7d6bb29d9ac6939da8372512237a9c51f74ff0a970524f2" )
IMAGES+=( "nextcloud:33.0.2-apache@sha256:2176a451aa8fbd9f003a3d745978377e9a5213850e0181f4bcb24be63885175b" )

find_index() {
	local -r value="${1}"
	shift
	local -r array=("$@")

	for i in "${!array[@]}"; do
		if [[ "${array[$i]}" == "${value}" ]]; then
			echo $i
			exit
		fi
	done

	echo -1
}

wait_for_value_in_file () {
	local -r file="${1}"
	local -r str="${2}"
	local -r max_seconds="${3}"

	echo "Searching for '${str}' inside: ${file}"

	for i in $(seq 1 "${max_seconds}"); do
		echo "Attempt: ${i}"
		if cat "${file}" | grep --quiet "${str}"; then
			return
		fi
		sleep 1
	done

	echo "Failed after ${max_seconds} seconds to find '${str}' inside: ${file}"
	exit 1
}

check_compose_file () {
	local -r image="${1}"

	web_image=$(cat "${APP_COMPOSE_FILE}" 2> /dev/null | yq '.services.web.image' || true)
	cron_image=$(cat "${APP_COMPOSE_FILE}" 2> /dev/null | yq '.services.cron.image' || true)

	if [[ "${web_image}" != "${image}" ]] || [[ "${cron_image}" != "${image}" ]]; then
		echo "The docker-compose.yml now looks bad. Restoring..."

		mv "${APP_COMPOSE_BACKUP_FILE}" "${APP_COMPOSE_FILE}"

		exit
	fi
}

get_version() {
	cat "${CONFIG_PHP_FILE}" | grep "'version'[[:space:]]=>[[:space:]]" | awk -F"'" '{print $4}'
}

get_major_version() {
	echo "${1%%.*}"
}

# Если файл конфигурации Nextcloud еще не существует
# Тогда скорее всего это новая установка
# Поэтому делать нечего
if [[ ! -f "${CONFIG_PHP_FILE}" ]]; then
	exit
fi

nextcloud_version=$(get_version)
nextcloud_major_version=$(get_major_version "$nextcloud_version")

echo "Active Nextcloud Version: ${nextcloud_version}"
echo "Active Nextcloud Major Version: ${nextcloud_major_version}"

# проверьте, добавлен ли к активной версии "-patch", и выйдите, если да, мы позволяем миграции завершиться
# мы добавляем "-patch" в версию ниже во время миграции
if [[ "${nextcloud_version}" == *"-patch"* ]]; then
	echo "Active Nextcloud version is undergoing migration. Exiting..."
	exit
fi

# Проверьте, есть ли активная основная версия в списке миграции
active_version_idx=$(find_index "${nextcloud_major_version}" "${VERSIONS[@]}")
if [[ "${active_version_idx}" == "-1" ]]; then
	echo "Active major version is not supported in the list of migrations"
	exit
fi

# Проверьте, обновлено ли уже
if [[ "${VERSIONS[-1]}" == "${nextcloud_major_version}" ]]; then
	echo "Nextcloud is already on the latest major version. No migration needed."
	exit
fi

# Перебирать версии, игнорируя предыдущие версии.
for i in "${!VERSIONS[@]}"; do
	[[ "${i}" -le "${active_version_idx}" ]] && continue

	version="${VERSIONS[$i]}"
	image="${IMAGES[$i]}"

	echo "Migrating to major version: ${version} (${image})"
	echo

	cp --archive "${APP_COMPOSE_FILE}" "${APP_COMPOSE_BACKUP_FILE}"

	yq -i ".services.web.image = \"${image}\"" "${APP_COMPOSE_FILE}"
	yq -i ".services.cron.image = \"${image}\"" "${APP_COMPOSE_FILE}"

	check_compose_file "${image}"

	nextcloud_version=$(get_version)
	sed -i "s/${nextcloud_version}/${nextcloud_version}-patch/" "${CONFIG_PHP_FILE}"

	"${DFWEBOS_ROOT}/scripts/app" start nextcloud

	echo "Waiting for update to complete..."

	# Подождите, пока Nextcloud перейдет в режим обслуживания.
	# Указание на то, что процесс обновления начался.
	wait_for_value_in_file "${CONFIG_PHP_FILE}" "'maintenance'[[:space:]]=>[[:space:]]true" 300

	# Подождите, пока Nextcloud выйдет из режима обслуживания.
	# Указание на завершение процесса обновления
	wait_for_value_in_file "${CONFIG_PHP_FILE}" "'maintenance'[[:space:]]=>[[:space:]]false" 300

	"${DFWEBOS_ROOT}/scripts/app" stop nextcloud

	# Удалить изображение промежуточной версии
	# Если это не последнее изображение
	# В противном случае его придется загрузить заново
	if [[ "${version}" != "${VERSIONS[-1]}" ]]; then
		echo "Deleting intermediary image: ${image}"

		docker rmi "${image}" || true
	fi
done

rm -rf "${APP_COMPOSE_BACKUP_FILE}"

echo "Migration completed successfully"
