#!/bin/bash
set -eu
set -x

echo "Устаревшая версия обновления! Восспользуйтесь утилитами eva_admin для обновления"
exit 1

### --help Info: Скрипт накатывает указанный дистрибутив и запускает патчи.
### --help Info: Не предусматривает ручной запуск.
### --help Usage: update_apply.sh dist_dir
### --help Example:

. /opt/fox_utils/crab_sys.sh

declare ARG_1 ARG_PATCH_FOR
sys::arg_parse "$@"

declare INSTALLATION_TYPE=box
. /opt/CONFIG

declare DIST_DIR="$ARG_1"
declare PATCH_FOR_DIST_DIR="${ARG_PATCH_FOR:-}"


patch_patch_magic_dir() {
	local patch_dir="$1" patch_for_dir="$2" app="$3"
	echo
	echo "Patch patch $patch_dir $app" >&2
	# --existing - заменяем существующие патчи, но не добавляем которых нет
	# --delete - если патч удалили ?
	# "$patch_for_dir/eva_opt/./$app/alembic/versions"
	rsync --existing --relative \
		--recursive --links --times \
		--stats --checksum --verbose \
		"$patch_for_dir/eva_opt/./$app/patch" \
		"/opt/"

	# Нам нужны миграции target версии, т.к. версия базы может быть новее, чем алембика в патче
	#  Такое бывает при переходе с девел на интегру(или при мердже)
	#  и в девел добавлялись новые миграции.
	#  Но логика наката, должна делать upgrade на головы патча.
	rsync --relative \
		--archive --delete \
		--stats --checksum --verbose \
		"$patch_for_dir/eva_opt/./$app/alembic/versions" \
		"/opt/"
	return 0
}


check_update() {
	local eva_size
	if [[ ! -d "$DIST_DIR/eva_opt" ]]; then
		echo "Ошибка! Нет обновления для opt" >&2
		exit 1
	fi
	set -o pipefail
	eva_size="$(du -s "$DIST_DIR/eva_opt" | awk '{print $1}')"
	set +o pipefail
	# Меньше 100Мб
	if [[ $eva_size -lt 100000 ]]; then
		echo "Ошибка обновления! Размер opt меньше 100Мб. $DIST_DIR" >&2
		exit 1
	fi
	if [[ -d "$DIST_DIR/eva_root" ]]; then
		set -o pipefail
		eva_size="$(du -s "$DIST_DIR/eva_root" | awk '{print $1}')"
		set +o pipefail
		# Меньше 2Гб
		if [[ $eva_size -lt 2000000 ]]; then
			echo "Ошибка обновления! Размер root меньше 2Гб. $DIST_DIR" >&2
			exit 1
		fi
	fi
	return 0
}


apply_files() {
	local app
	# --progress --verbose
	# Обновления для root может не быть
	if [ -d "$DIST_DIR/eva_root" ]; then
		echo "Обновляю root из $DIST_DIR"
		rsync \
			--exclude=/var/cache/eva_dist \
			--exclude=/opt --exclude=/dev --exclude=/mnt --exclude=/proc \
			--exclude=/run --exclude=/sys --exclude=/tmp --exclude=/var/log \
			--exclude=/etc/nginx/conf.d \
			--exclude=/etc/hostname --exclude=/etc/hosts --exclude=/etc/resolv.conf \
			--stats --block-size=40507 -c --timeout=1200 -a --delete \
			"$DIST_DIR/eva_root/" /
	fi

	echo "Обновляю opt из $DIST_DIR"
	rsync \
		--exclude=/CONFIG --exclude=custom/ --exclude="/*/jwt_rsa*" \
		--exclude=/var --exclude=/files --exclude=/files.meta --exclude=/etc \
		--exclude=/crm/common/static/avatar --exclude=/crm/common/static/forms \
		--exclude=/crm/backup \
		--exclude=/bin/update_scripts \
		--exclude="/eva_version*" \
		--stats --block-size=40507 -c --timeout=1200 -a --delete \
		"$DIST_DIR/eva_opt/" /opt/

	rsync -c --timeout=5 -a --delete "$DIST_DIR/eva_opt/eva_version" /opt/eva_version.update

	# Хитрая логика обновления патчей
	if [[ $PATCH_FOR_DIST_DIR ]]; then
		for app in account crm; do
			patch_patch_magic_dir "$DIST_DIR" "$PATCH_FOR_DIST_DIR" "$app"
		done
	fi
	return 0
}


alembic_heads() {
	set -e
	local app="$1"
	if [[ $PATCH_FOR_DIST_DIR ]]; then
		# Нужно взять головы из DIST_DIR, т.к. в alembic версии для PATCH_FOR_DIST_DIR
		# Красивее - замокать alembic.ini, и указать папку с миграциями
		# Но пока делаем хаком(не очень надёжным): копируем нужный ап и смотрим версии в нём.
		rsync --archive --delete \
			--stats --checksum \
			"$DIST_DIR/eva_opt/$app/" \
			/opt/update_app >&2  # stdout нельзя засорять.
		(
			cd /opt/update_app
			set -o pipefail
			# skip strongbash034.
			alembic heads | cut -d " " -f 1
			set +o pipefail
		)
		rm -rf --one-file-system /opt/update_app
	else
		echo heads
	fi
	return 0
}


update_hook(){
	/etc/init.d/postgresql start
	/etc/init.d/redis-server start
	# TODO messenger whatsapp converter
	# TODO account миграции руками!! ??
	local app app_list=crm head
	if [[ ${INSTALLATION_TYPE:-box} = box ]]; then
		app_list="crm account"
	fi
	# Применим конфигурацию перед запуском патчей
	/opt/bin/eva_configure --dont-restart-services
	for app in $app_list; do
		echo "Запускаем миграции БД для $app"
		(
			cd "/opt/$app"
			for head in $(alembic_heads "$app"); do
				alembic upgrade "$head"
			done
			python3 manage.py patch
		)
	done
	/etc/init.d/postgresql stop
	/etc/init.d/redis-server stop
	return 0
}


main(){
	check_update
	apply_files
	update_hook
	mv /opt/eva_version.update /opt/eva_version
	return 0
}


main

exit 0
