VENV := .venv
PYTHON := $(VENV)/bin/python
PIP := $(VENV)/bin/pip
WHEELS_DIR := wheels
REQUIREMENTS := requirements.txt
MANAGE := cd src/ && ../$(PYTHON) manage.py
# .env для Django и воркера: те же переменные, что читает docker compose
ifneq (,$(wildcard .env))
include .env
export $(shell sed -n 's/^\([A-Z_][A-Z0-9_]*\)=.*/\1/p' .env)
endif
SERVERUS := cd src/ && ../$(PYTHON) -m serverus
# доступы к серверам, настроенным вручную через serverus (папка в .gitignore)
SERVERUS_ACCESS_DIR := $(abspath extra/serverus)
# свой CA для серверов без Let's Encrypt (ca=yes), создается при первом запуске
SERVERUS_CA_DIR := $(SERVERUS_ACCESS_DIR)/ca
SERVERUS_CA = $(if $(filter yes,$(ca)),--ca $(SERVERUS_CA_DIR))

MAKECMDGOALS_TARGETS := install freeze wheels sync sync-offline clean help
PKG := $(filter-out $(MAKECMDGOALS_TARGETS),$(MAKECMDGOALS))

.PHONY: install freeze wheels sync sync-offline clean help venv dj_makemigrations dj_migrate dj_superuser dj_run dj_test dj_startapp dj_worker dj_secrets dj_backup dj_restore dj_check_points docker_build docker_up serve_ssh serverus_xui serverus_key serverus_cert serverus_outbound serverus_release

help:
	@echo "make install <pkg> [<pkg> ...]  - установить пакет(ы) в $(VENV), обновить $(REQUIREMENTS), собрать wheel в $(WHEELS_DIR)/"
	@echo "make sync                       - установить все пакеты из $(REQUIREMENTS) (из индекса)"
	@echo "make sync-offline               - установить все пакеты из $(REQUIREMENTS) только из $(WHEELS_DIR)/, без обращения к индексу"
	@echo "make freeze                     - перезаписать $(REQUIREMENTS) текущим состоянием окружения"
	@echo "make wheels                     - собрать wheel для всех пакетов из $(REQUIREMENTS)"
	@echo "make clean                      - удалить $(WHEELS_DIR)/"
	@echo "make dj_secrets                 - сгенерировать недостающие секреты в .env"
	@echo "make dj_backup [keep=14]        - бэкап базы в extra/backups, keep - сколько последних оставить"
	@echo "make dj_restore file=<dump>     - восстановить базу из бэкапа (сайт и воркер остановлены)"
	@echo "make docker_build / docker_up   - собрать образ и поднять все в docker (профиль app)"
	@echo "make serverus_xui ip=<ip> password=<root_password> [domain=<domain>] [ssl=no] [ca=yes] - настроить свежий сервер и поставить 3x-ui, доступы в $(SERVERUS_ACCESS_DIR)/<ip>/"
	@echo "make serverus_key ip=<ip> action=add|del|stats name=<name> - ключ на панели, настроенной через serverus_xui"
	@echo "make serverus_cert ip=<ip> [domain=<domain>] [ca=yes] - сертификат панели на домен или на ip"
	@echo "make serverus_outbound ip=<ip> [proxy=socks5://...|cf_warp] - исходящий прокси, без proxy - напрямую"
	@echo "make serverus_release ip=<ip> [password=<new_root_password>] - вернуть сервер, настроенный через serverus_xui: вход по паролю на 22 порт"

venv:
	@test -d $(VENV) || python3 -m venv $(VENV)

install: venv
ifeq ($(strip $(PKG)),)
	$(error Укажите пакет: make install <package>, например make install redis)
endif
	echo $(PKG)
	$(PIP) install --upgrade $(PKG)
	$(PIP) freeze > $(REQUIREMENTS)
	@mkdir -p $(WHEELS_DIR)
	$(PIP) wheel $(PKG) -w $(WHEELS_DIR)
	@echo "Готово: $(PKG) установлен, $(REQUIREMENTS) обновлён, wheel-пакеты в $(WHEELS_DIR)/"

sync: venv
	$(PIP) install -r $(REQUIREMENTS)

sync-offline: venv
	$(PIP) install --no-index --find-links=$(WHEELS_DIR) -r $(REQUIREMENTS)

freeze: venv
	$(PIP) freeze > $(REQUIREMENTS)

wheels: venv
	@mkdir -p $(WHEELS_DIR)
	$(PIP) wheel -r $(REQUIREMENTS) -w $(WHEELS_DIR)

clean:
	rm -rf $(WHEELS_DIR)

# позволяет передавать имя пакета как аргумент: make install redis
%:
	@:

dj_makemigrations:
	$(MANAGE) makemigrations

dj_migrate:
	$(MANAGE) migrate

dj_superuser:
	$(MANAGE) createsuperuser

dj_run:
	$(MANAGE) runserver

dj_test:
	$(MANAGE) test --settings=MyPointVPN.settings.test

dj_worker:
	$(MANAGE) rundramatiq

# секреты в .env: дописывает только отсутствующие и пустые, FIELD_ENCRYPTION_KEYS не перезаписывает
dj_secrets:
	$(MANAGE) generate_secrets --env-file ../.env

# бэкап базы в extra/backups: make dj_backup [keep=14]
dj_backup:
	$(MANAGE) backup $(if $(keep),--keep $(keep))

# восстановление: make dj_restore file=extra/backups/<файл>.dump. Сайт и воркер должны быть остановлены
dj_restore:
	@test -n "$(file)" || { echo "Укажите бэкап: make dj_restore file=extra/backups/<файл>.dump"; exit 1; }
	$(MANAGE) restore $(abspath $(file))

# перезапустить ежедневные проверки точек (нужен воркер)
dj_check_points:
	$(MANAGE) check_points

# образ приложения: wheels/ в .gitignore, поэтому собираются перед сборкой
docker_build: wheels
	docker compose --profile app build

# инфраструктура, миграции, сайт и воркер в docker
docker_up:
	docker compose --profile app up -d

dj_startapp:
	$(MANAGE) startapp $(app)

# ручной вход на сервер точки с ключом из базы: make serve_ssh ip=<ip> [cmd='uptime']
serve_ssh:
	@test -n "$(ip)" || { echo "Укажите сервер: make serve_ssh ip=<ip> [cmd='<команда>']"; exit 1; }
	$(MANAGE) serve_ssh $(ip) $(if $(cmd),-- $(cmd))

serverus_xui:
	@test -n "$(ip)" -a -n "$(password)" || { echo "Укажите сервер: make serverus_xui ip=<ip> password=<root_password>"; exit 1; }
	$(SERVERUS) xui $(ip) '$(password)' --out $(SERVERUS_ACCESS_DIR)/$(ip) $(if $(domain),--domain $(domain)) $(if $(filter no,$(ssl)),--no-ssl) $(SERVERUS_CA)

serverus_key:
	@test -n "$(ip)" -a -n "$(action)" -a -n "$(name)" || { echo "Укажите ключ: make serverus_key ip=<ip> action=add|del|stats name=<name>"; exit 1; }
	$(SERVERUS) key $(action) '$(name)' --out $(SERVERUS_ACCESS_DIR)/$(ip)

serverus_cert:
	@test -n "$(ip)" || { echo "Укажите сервер: make serverus_cert ip=<ip> [domain=<domain>]"; exit 1; }
	$(SERVERUS) cert $(domain) --out $(SERVERUS_ACCESS_DIR)/$(ip) $(SERVERUS_CA)

serverus_outbound:
	@test -n "$(ip)" || { echo "Укажите сервер: make serverus_outbound ip=<ip> [proxy=socks5://...|cf_warp]"; exit 1; }
	$(SERVERUS) outbound '$(proxy)' --out $(SERVERUS_ACCESS_DIR)/$(ip)

serverus_release:
	@test -n "$(ip)" || { echo "Укажите сервер: make serverus_release ip=<ip>"; exit 1; }
	$(SERVERUS) release --out $(SERVERUS_ACCESS_DIR)/$(ip) $(if $(password),--password '$(password)')
