#!/bin/bash

set -eu
### --help Info: debug_manager.sh - утилита для отключения дебага Евы.
### --help Usage: debug_manager.sh [enable|disable] [--restart]
### --help Usage:     enable - включит дебаг в конфигурации аппа
### --help Usage:     disable - выключит дебаг в конфигурации аппа
### --help Usage:     --restart - перезапустит апп, если конфигурация поменялась;
### --help Usage:                 иначе, это произойдёт по cron
### --help Usage:     без параметров - пройдёт по всем аппам, проверит, что дебаг
### --help Usage:                      выключен; запомнит время, если обнаружет, что
### --help Usage:                      включили и выключит через пять дней при очередном
### --help Usage:                      запуске по cron.
### --help Usage: debug_manager.sh [enable|disable] --restart
### --help Usage: debug_manager.sh [enable|disable] --restart
### --help Example: debug_manager.sh
### --help Example: debug_manager.sh disable --restart
### --help Example: debug_manager.sh enable

. /opt/fox_utils/crab_sys.sh

date --rfc-3339=seconds

[ "${1:-}" = "--help" ] && sys::usage "$@"

declare ARG_1 ARG_LIST
sys::arg_parse "$@"

# Для K8s нужно будет сделать динамический, в аппе.
# Потом убрать скрипт, т.к. решение подойдёт и для коробки и для облака.
# Пока для K8s дебаг определяет админ вручную.
set -x
if [[ "${EVA_DEPLOY_TYPE:-}" == "k8s" ]]; then
	echo "INFO debug_manager не работает в кластере" >&2
	exit 0
elif [[ ! "${EVA_DEPLOY_TYPE:-}" =~ ^((box|box-lxc|cloud-lxc|k8s)|cloud.*)$ ]]; then
	echo "ERROR Неизвестный тип деплоя" >&2
	exit 0
fi


declare NOW DAYS LAST_UPDATE DEBUG NEED_RESTART APP_STATE_CHANGED
NOW="$(date +%s)"
DAYS=4
DEBUG="True"
NEED_RESTART="FALSE"

declare CUR_DEBUG_VALUE

_get_debug_value(){
	############################################################################
	# Функция пытается получить текущее состояние дебага.
	# Вычисленное значение сохранит в глобальной переменной.
	# Глобальная переменная, т.к. тут может падать, а вариант
	# выполнять в сабшеле и делать echo в функции - скрывал место ошибки.
	############################################################################
	local d common_config custom_config config value
	d="$1"
	common_config="$2"
	custom_config="$3"
	cd "$d"
	# Пытаемся получить с работающего приложения, т.к. это наиболее точно.
	python3 manage.py shell "print(config.DEBUG)" &>/dev/null && ret=0 || ret=$?
	if ((ret == 0)); then
		value="$(python3 manage.py shell "print(config.DEBUG)" 2> /dev/null)"
		value="$(grep -e ^True$ -e ^False$<<<$value)"
		value="${value:-"$DEBUG"}"
		CUR_DEBUG_VALUE="$value"
		return 0
	fi
	# Если приложение не запущено или не ответило, ищем в конфиге.
	# По приоритету: custom, common, cmf common.
	# Если в конфигах нет, возможно зашито в коде приложения.
	# Тогда берём значение по-умолчанию.
	if grep -q '^DEBUG' "$custom_config" &>/dev/null; then
		config="$custom_config"
	elif grep -q '^DEBUG' "$common_config" &>/dev/null; then
		config="$common_config"
	elif grep -q '^DEBUG' "$d/cmf/config.py" &>/dev/null; then
		config="$d/cmf/config.py"
	else
		CUR_DEBUG_VALUE="$DEBUG"
		return 0
	fi
	value=$(sed 's/DEBUG\s*=\s*//g'<<<"$(grep -w -e "^DEBUG\s*=" $config)")
	CUR_DEBUG_VALUE="${value:-$DEBUG}"
	return 0
}


_set_debug_value(){
	local config="$1"
	local value="$2"
	if [[ ! -f "$config" ]]; then
		echo "Файл $config отсутствует. Создаём."
		echo "DEBUG = $value" > $config
	elif grep -q '^DEBUG' $config; then
		sed -i "s/^DEBUG\s*=.*/DEBUG = $value/g" $config
	else
		echo "DEBUG = $value" >> $config
	fi
	return 0
}


switch_debug_value(){
	local d app common_config custom_config debug_current_value value
	d="$1"
	app="$2"
	common_config="$3"
	custom_config="$4"
	debug_current_value="$5"
	echo "Меняю статус дебага для $app: debug_current_value=$debug_current_value"
	if [[ "$debug_current_value" == "True" ]]; then
		_set_debug_value "$custom_config" False
	else
		_set_debug_value "$custom_config" True
	fi
	# Рестарт должен делать либо cron, либо флаг --restart
	# NEED_RESTART="TRUE"
	APP_STATE_CHANGED=TRUE
	return 0
}


cron_disabler(){
	local d app common_config custom_config
	local debug_marker debug_current_value enabled_date msg
	d="$1"
	app="$2"
	common_config="$3"
	custom_config="$4"
	debug_current_value="$5"
	debug_marker="$d/custom/debug_disabler.marker"
	if [[ "$debug_current_value" == "False" ]]; then
		# Могли выключить вручную, тогда маркер больше не нужен
		[[ -f "$debug_marker" ]] && echo "Дебаг выключен. Удаляю маркер $debug_marker"
		[[ -f "$debug_marker" ]] && rm -f "$debug_marker"
		return 0
	fi
	if [[ ! -f "$debug_marker" ]] || [[ ! -s "$debug_marker" ]]; then
		echo $NOW > "$debug_marker"
		echo "Дебаг приложения $app включен, запоминаю дату"
		return 0
	fi
	enabled_date="$(<"$debug_marker")"
	if ((NOW > enabled_date+3600*24*DAYS)); then
		NEED_RESTART="TRUE"
		msg="Отключаю дебаг приложения $app."
		msg+=" debug_current_value=$debug_current_value"
		msg+=", enabled_date=$(date  --rfc-3339=seconds -d @$enabled_date)"
		echo "$msg"
		_set_debug_value "$custom_config" False
		rm -f "$debug_marker"
	fi
	return 0
}


main(){
	local d action app common_config custom_config debug_current_value value
	action="${1:-}"
	for d in $(find /opt/ -mindepth 1 -maxdepth 1 -type d); do
		app="${d##*/}"
		common_config="$d/common/config.py"
		custom_config="$d/custom/config.py"
		if [[ ! -f "$common_config" ]]; then
			continue
		fi
		echo "$d"
		_get_debug_value "$d" "$common_config" "$custom_config"
		debug_current_value="$CUR_DEBUG_VALUE"
		echo "$d debug_current_value=\"$debug_current_value\""
		if [[ "$action" == "enable" ]]; then
			value="True"
		elif [[ "$action" == "disable" ]]; then
			value="False"
		else
			# По-умолчанию выключаем дебаг через N ней
			cron_disabler "$d" "$app" "$common_config" "$custom_config" "$debug_current_value"
			continue
		fi
		if [[ "$debug_current_value" != "$value" ]]; then
			switch_debug_value "$d" "$app" "$common_config" "$custom_config" "$debug_current_value"
		fi
	done
	if [[ "$NEED_RESTART" == "TRUE"
		|| "${ARG_RESTART:-}" == "TRUE"
		&& "${APP_STATE_CHANGED:-}" == "TRUE" ]]; then
		/opt/bin/services restart
	fi
	return 0
}

main "$@"

date --rfc-3339=seconds
exit 0
