#!/bin/bash
set -eu

echo "$0 $@ [$$] START" >&2
if [ "${1:---help}" = "--help" ]; then
	echo 'Info: CLI для проектов на CMF'
	echo \
		"Usage: ./cmf/cmf_cli [init|start|init-db|load-demo-data|generate-rsa-keypair|auth2ldif|test]"
	echo 'Example: ./cmf/cmf_cli init'
	echo \
'Example: ./cmf/cmf_cli auth2ldif --domain example.com --password 123 -o /opt/ldaptor/db.ldif
'
	echo 'Example install contrib extentions:'
	for ext in $(ls ./cmf/contrib); do
		echo "./cmf/cmf_cli install $ext"
	done
	echo 'all command list'
	grep '__.*()' $0 | grep -v grep | sed 's/^__//;s/().*{//'
	exit 0
fi

if [ ! -x ./cmf/cmf_cli ]; then
	echo "LOG_ERROR нужно запускать ./cmf/cmf_cli"
	exit 1
fi

__init_environment() {
	local sudo_cmd=
	if [ "$(id -u)" != 0 ]; then
		sudo_cmd="sudo"
	else
		sudo_cmd=""
	fi
	if command -v yum; then
		$sudo_cmd yum install -y python3 gcc python3-devel
	elif command -v apt; then
		echo "не проверено"
		$sudo_cmd apt install -y python3 gcc python3-dev
	else
		echo "apt or yum required"
		return 1
	fi
	python3 -m pip install --user --no-cache-dir -r cmf/requirements.txt
	return 0
}

__init() {
	__init_environment
	bash -x ./cmf/contrib/angular/install.sh
	bash -x ./cmf/contrib/api/install.sh
	bash -x ./cmf/contrib/crud/install.sh
	bash -x ./cmf/contrib/auth/install.sh
	bash -x ./cmf/contrib/example/install.sh
	bash -x ./cmf/contrib/new_project/install.sh
	__generate_rsa_keypair
	echo 'Внимание1. PLZ reopen console or start /bin/bash !!!'
	echo 'Внимание2. Модуль auth работает только через https'
	echo 'Внимание3. Укажите AUTH_SESSION_COOKIE_DOMAIN /opt/cmf/custom/config.py'
	return 0
}

__auth2ldif() {
	python3 -m bin.auth2ldif "$@"
	return 0
}

__start() {
	if [ -d ".git" ]; then
		export DEPLOY_VERSION="$(cat .git/refs/heads/master)"
	fi
	set +x
	echo "##########################"
	echo "ЗАПУСТИТЕ: python3.6 manage.py start # порт 8080 зашит"
	echo "ЗАПУСТИТЕ: npx ng serve --host 0.0.0.0 --port 8000 --publicHost=foxcrm.carbonsoft.ru"
	echo "--publicHost по дефолту равен --host"
	echo "firewall-cmd --zone=public --add-port=8080/tcp --permanent"
	echo "firewall-cmd --zone=public --add-port=8000/tcp --permanent"
	echo "firewall-cmd --reload"
	echo "##########################"
	return 0
}

__replace_template_vars(){
	local module_name="$1"
	local model_name="$2"
	local filename="$3"

	local module_name_camel_cap="$(sed -r 's/(^|_)([a-z])/\U\2/g' <<<"$module_name")"
	local model_name_camel_cap="$(sed -r 's/(^|_)([a-z])/\U\2/g' <<<"$model_name")"

	local module_name_snake="$(sed -r 's/([a-z0-9])([A-Z])/\1_\L\2/g' <<<"$module_name")"
	module_name_snake="${module_name_snake,,}"
	local model_name_snake="$(sed -r 's/([a-z0-9])([A-Z])/\1_\L\2/g' <<<"$model_name")"
	model_name_snake="${model_name_snake,,}"

	local module_name_kebab="${module_name_snake//_/-}"
	local model_name_kebab="${model_name_snake//_/-}"

	sed -i "s/@@@module_name_snake###/$module_name_snake/g" "$filename"
	sed -i "s/@@@model_name_snake###/$model_name_snake/g" "$filename"

	sed -i "s/@@@ModuleName###/$module_name_camel_cap/g" "$filename"
	sed -i "s/@@@ModelName###/$model_name_camel_cap/g" "$filename"

	sed -i "s/@@@module-name###/$module_name_kebab/g" "$filename"
	sed -i "s/@@@model-name###/$model_name_kebab/g" "$filename"

	return 0
}

__generate_model(){
	local module_name="$1"
	local model_name="$2"

	if [[ "$model_name" == *_* ]]; then
		echo "Имя модели должно быть CamelCase. Пример: CmfAuth, CrmInvoice"
		exit 255
	fi

	if [[ "$(sed 's/[A-Z]/_/g' <<<"$model_name")" != *_*_* ]]; then
		echo "Имя модели должно начинаться с префикса. Пример: CmfAuth, CrmInvoice"
		exit 255
	fi

	local module_name_camel_cap="$(sed -r 's/(^|_)([a-z])/\U\2/g' <<<"$module_name")"
	local model_name_camel_cap="$(sed -r 's/(^|_)([a-z])/\U\2/g' <<<"$model_name")"

	local module_name_snake="$(sed -r 's/([a-z0-9])([A-Z])/\1_\L\2/g' <<<"$module_name")"
	module_name_snake="${module_name_snake,,}"
	local model_name_snake="$(sed -r 's/([a-z0-9])([A-Z])/\1_\L\2/g' <<<"$model_name")"
	model_name_snake="${model_name_snake,,}"

	local module_name_kebab="${module_name_snake//_/-}"
	local model_name_kebab="${model_name_snake//_/-}"

	echo "this_is_the_string" | sed -r 's/(^|_)([a-z])/\U\2/g'
	if [ ! -d "modules/$module_name" ]; then
		echo "Warning: No such module: $module_name"
		__generate_module "$module_name"

		cp ./cmf/bin/templates/router.tpl \
			"modules/$module_name/angular/$module_name_kebab-routing.module.ts"
		__replace_template_vars \
			"$module_name" \
			"$model_name" \
			"modules/$module_name/angular/$module_name_kebab-routing.module.ts"
	fi

	npx ng g component "../$module_name/angular/$model_name_kebab-list" "--module=$module_name_kebab"
	npx ng g component "../$module_name/angular/$model_name_kebab-detail" "--module=$module_name_kebab"

	cp ./cmf/bin/templates/model.tpl "modules/$module_name/models/$model_name_snake.py"
	__replace_template_vars "$module_name" "$model_name" \
		"modules/$module_name/models/$model_name_snake.py"

	cp ./cmf/bin/templates/fields.tpl "modules/$module_name/fields/$model_name_snake.py"
	__replace_template_vars "$module_name" "$model_name" \
		"modules/$module_name/fields/$model_name_snake.py"

	cp ./cmf/bin/templates/crud_list_component.tpl \
		"modules/$module_name/angular/$model_name_kebab-list/$model_name_kebab-list.component.html"
	__replace_template_vars "$module_name" "$model_name" \
		"modules/$module_name/angular/$model_name_kebab-list/$model_name_kebab-list.component.html"

	cp ./cmf/bin/templates/crud_detail_component.tpl \
		"modules/$module_name/angular/$model_name_kebab-detail/$model_name_kebab-detail.component.html"
	__replace_template_vars "$module_name" "$model_name" \
		"modules/$module_name/angular/$model_name_kebab-detail/$model_name_kebab-detail.component.html"

	return 0
}

__generate_module(){
	local name="$1"
	local name_kebab="${1//_/-}"
	local name_cap="${1^}"
	npx ng g module --flat "../$name/angular/$name" --routing --module=app
	npx ng g component --flat "../$name/angular/$name" "--module=$name_kebab"
	touch "modules/$name/__init__.py"
	echo "====== Module $name ======" > "modules/$name/README.md"
	mkdir "modules/$name/fields"
	mkdir "modules/$name/models"
	touch "modules/$name/fields/__init__.py"
	touch "modules/$name/models/__init__.py"

	sed -i "s/CommonModule/CmfCommonModule/g" \
		"modules/$name/angular/$name_kebab.module.ts"

	sed -i "s/@angular\/common/..\/..\/..\/common\/angular\/cmf-common.module/g" \
		"modules/$name/angular/$name_kebab.module.ts"

	cp ./cmf/bin/templates/component.tpl "modules/$name/angular/$name_kebab.component.html"

	__replace_template_vars \
		"$name" \
		"" \
		"modules/$name/angular/$name_kebab.component.html"

	return 0
}

__generate_todo() {
	echo "TODO будет генерировать создание типичных модулей и прочего"
	echo '
	типо таких файлов
modules/tasks/angular/task-list/task-list.component.html

####
# <app-cmf-crud-list module="task" path="tasks"></app-cmf-crud-list>
####
'
	echo "пример: ./cmf/cmf-cli generate module task"
	echo "пример: ./cmf/cmf-cli generate module mail"
	echo "пример: ./cmf/cmf-cli generate module feed"
	echo "команда generate module должна создавать типичный модуль"
	echo "со всеми crud-компонентами, моделями и пр"
	echo "пример: ./cmf/cmf-cli generate component task-master --module=task"
	echo "команда generate module должна создавать типичный модуль"
	echo "со всеми crud-компонентами, моделями и пр"
	echo
	echo "Примеры команд ангуляра: "
	echo "
!!!! -d dry run

ng g module --flat ../tasks/angular/tasks --routing --module=app -d
ng g component --flat  ../tasks/angular/tasks  --module=tasks -d
ng g component ../tasks/angular/task-list  --module=tasks -d
ng g component ../tasks/angular/task-detail  --module=tasks -d

npx ng g module --flat ../../common/angular/crud/crud  --module=app
npx ng g component  ../../common/angular/crud/crud-read  --module=crud
npx ng g component  ../../common/angular/crud/crud-detail  --module=crud
npx ng g component  ../../common/angular/crud/crud-list  --module=crud
"
	return 0
}

__init_db() {
	python3 manage.py init_db
	return 0
}

__dump_db() {
	python3 manage.py dump_db $@
	return 0
}

__remove_old_backup() {
	find backup/ -mtime +1 -type f -delete
	return 0
}

__load_backup_today() {
	local today="$(date +%Y)_$(date +%m)/$(date +%d)/"
	mkdir -p "backup/$today"
	rsync -azvP \
		"root@node8.carbonsoft.ru:/opt/fox_conf/vm/acrm.carbonsoft.ru/rootfs/var/backup/$today"\
		"backup/$today"
	return 0
}

__load_backup_latest() {
	set -e
	local node="root@node8.carbonsoft.ru"
	local path="/opt/fox_conf/vm/acrm.carbonsoft.ru/rootfs/var/backup"
	local glob="*_*/*/backup_*.json"
	local script=""
	script="ls -1d $path/$glob | tail -n 1"
	local last_backup_full_name="$(ssh $node "$script")"
	local last_backup_name="${last_backup_full_name/$path\//}"
	mkdir -p "$(dirname backup/$last_backup_name)"
	rsync -az "$node:$path/$last_backup_name" "$(dirname backup/$last_backup_name)/"
	echo "$last_backup_name"
	return 0
}

__restore_db() {
	python3 manage.py restore_db $@
	return 0
}

__devel_sync_prod_db_sqlite() {
	local last_backup_name=$(__load_backup_latest)
	mkdir -p "backup/db/"
	mv db.sqlite3 "backup/db/db.sqlite3.$(date +%s)"
	__restore_db "backup/$last_backup_name"
	return 0
}


__devel_sync_db_mysql() {
	local remote="$1"
	local mysql_passwd=""

	echo "Скачиваю бэкап базы с $remote"
	ssh -J root@node8.carbonsoft.ru "$remote" \
		mysqldump -uroot -pkosmos8800 crmdb > "backup/acrm.sql"

	read -s -p "Ведите локальный пароль MySQL:" mysql_passwd
	echo
	if [ ! -z "$mysql_passwd" ]; then
		mysql_passwd="-p$mysql_passwd"
	fi

	echo "Делаю бэкап локальной базы в backup/local.sql"
	mysqldump -uroot $mysql_passwd crmdb > "backup/local.sql"

	echo "Пересоздаю базу"
	echo "\
DROP DATABASE IF EXISTS crmdb;\
CREATE DATABASE crmdb DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;\
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));"\
	| mysql -uroot $mysql_passwd crmdb

	echo "Восстанавливаю данные"
	cat "backup/acrm.sql" | mysql -uroot $mysql_passwd crmdb

	echo "Выполняю миграции"
	alembic upgrade head
	return 0
}

__devel_sync_acrm_db_mysql() {
	__devel_sync_db_mysql "root@10.50.15.195"
	return 0
}

__devel_sync_bcrm_db_mysql() {
	__devel_sync_db_mysql "root@10.50.16.6"
	return 0
}

__load_demo_data() {
	python3 manage.py load_demo_data
	return 0
}

__generate_rsa_keypair() {
	python3 manage.py generate_rsa_keypair
	return 0
}
__install() {
	bash -x "./cmf/contrib/$1/install.sh"
	return 0
}

__update() {
	# pull crm
	git pull origin master
	cd cmf
	# pull cmf
	git pull origin master
	cd ..
	# move database to backup
	mkdir -p backup
	mv "db.sqlite3" "backup/db.sqlite3.bk.$(date +%s)" || true
	mv "dist" "backup/dist.bk.$(date +%s)" || true
	__init_db
	__load_demo_data
	npm run build -- --prod
	systemctl restart cmf
	return 0
}

__test() {
	local test_path="${1:-tests}"
	pytest $test_path
	return 0
}

CMD="${1//-/_}"
shift
# set -x
"__$CMD" "$@"

echo "$0 $@ [$$] SUCCESS" >&2
exit 0
