ROOT_DIR?=$(abspath $(dir $(lastword $(MAKEFILE_LIST))))
UV?=uv
CONTAINER_TOOL?=podman
PACKAGE_NAME?=bkai-init
PACKAGE_VERSION?=$(shell cd ${ROOT_DIR} && $(UV) version --short)
IMAGE?=bkai-init:local
DEMO_IMAGE?=bkai-init-demo:local
IMAGE_BUILD_ARGS?=
DIST_DIR?=$(ROOT_DIR)/dist
CI_REPO_ROOT?=$(abspath $(ROOT_DIR)/../..)
CI_PYTHON?=python3
CI_HELPER=$(ROOT_DIR)/scripts/ci.py
ENV_FILE?=$(CI_REPO_ROOT)/.local/env_bkai_init
PACKAGE_FILE?=$(ROOT_DIR)/demo/package/bkai.yaml
TENANT_ID?=system
SPACE?=
RESOURCES?=
EXCLUDE_RESOURCES?=
CHECK?=false
PUBLISH?=false
PUBLISH_CONFIG_ONLY?=1
pytest = $(UV) run --project ${ROOT_DIR} --no-sync pytest -c ${ROOT_DIR}/pyproject.toml

.PHONY: ALL
ALL: test

${ROOT_DIR}/uv.lock: ${ROOT_DIR}/pyproject.toml
	cd ${ROOT_DIR} && $(UV) lock
	cd ${ROOT_DIR} && $(UV) lock --check

.PHONY: init
init: uv-install
	@echo "Project initialization complete."

.PHONY: uv-install
uv-install: ${ROOT_DIR}/uv.lock
	$(UV) --version
	cd ${ROOT_DIR} && $(UV) sync --extra test --inexact

.PHONY: test
test: uv-install
	$(eval path ?= ${ROOT_DIR}/tests)
	$(eval maxfail ?= --maxfail=2)
	${pytest} ${path} ${maxfail} ${args}

# Commit gate: always run the full offline suite, including generated packages and demo.
# Do not load ENV_FILE or accept a narrowed test path here.
.PHONY: check
check: uv-install
	${pytest} ${ROOT_DIR}/tests --maxfail=2

.PHONY: ci-test
ci-test: uv-install
	$(eval path ?= ${ROOT_DIR}/tests)
	${pytest} ${path} --maxfail=2 ${args}

# local-test never writes remote resources. Use local-sync explicitly for writes.
.PHONY: local-test local-validate local-show local-diff local-plan local-sync
local-test: local-validate

local-validate: uv-install
	@set -eu; \
		space="$(or $(SPACE),$${BKAI_SPACE_ID:-})"; \
		set --; if test -n "$$space"; then set -- --space "$$space"; fi; \
		$(UV) run --project "$(ROOT_DIR)" --no-sync bkai-init validate -f "$(PACKAGE_FILE)" "$$@"

local-show local-diff local-plan local-sync: uv-install
	@set -eu; \
		test -f "$(ENV_FILE)" || { echo "ENV_FILE does not exist; specify the local env file" >&2; exit 1; }; \
		env_file="$(ENV_FILE)"; case "$$env_file" in /*) ;; *) env_file="./$$env_file" ;; esac; \
		set -a; . "$$env_file"; set +a; \
		space="$(or $(SPACE),$${BKAI_SPACE_ID:-})"; \
		set --; if test -n "$$space"; then set -- --space "$$space"; fi; \
		$(UV) run --project "$(ROOT_DIR)" --no-sync bkai-init $(patsubst local-%,%,$@) \
		-f "$(PACKAGE_FILE)" --tenant-id "$(TENANT_ID)" \
		"$$@" \
		$(if $(filter local-sync,$@),--confirm) \
		$(foreach resource,$(RESOURCES),--resource "$(resource)") \
		$(if $(filter local-sync local-plan,$@),$(foreach resource,$(EXCLUDE_RESOURCES),--exclude-resource "$(resource)")) \
		$(if $(and $(filter local-diff,$@),$(filter true,$(CHECK))),--check) \
		$(if $(and $(filter local-sync local-plan,$@),$(filter true,$(PUBLISH))),--publish --publish_config_only="$(PUBLISH_CONFIG_ONLY)")

.PHONY: build
build:
	rm -rf "$(DIST_DIR)"
	cd "$(ROOT_DIR)" && $(UV) build --no-sources --out-dir "$(DIST_DIR)"

.PHONY: publish
publish: build
	cd "$(ROOT_DIR)" && $(UV) publish ${publish_args} "$(DIST_DIR)"/*

# Pipeline parameters and credentials are inherited from the process environment.
# Keep publication separate so both indexes receive the same checked artifacts.
.PHONY: ci-prepare ci-build ci-publish ci-snapshot
ci-prepare:
	@cd "$(CI_REPO_ROOT)" && $(CI_PYTHON) "$(CI_HELPER)" prepare

ci-build: ci-prepare
	@set -eu; \
		cd "$(ROOT_DIR)"; \
		original=$$(mktemp); \
		cp pyproject.toml "$$original"; \
		trap 'cp "$$original" pyproject.toml; rm -f "$$original"' EXIT; \
		$(UV) version --frozen "$$(cat "$(CI_REPO_ROOT)/bkai-build/version.txt")"; \
		$(MAKE) build DIST_DIR="$(CI_REPO_ROOT)/bkai-build/dist"
	$(CI_PYTHON) -m twine check --strict "$(CI_REPO_ROOT)"/bkai-build/dist/*
	$(UV) venv --clear --python "$(CI_PYTHON)" "$(CI_REPO_ROOT)/.bkai-smoke"
	$(UV) pip install --python "$(CI_REPO_ROOT)/.bkai-smoke/bin/python" "$(CI_REPO_ROOT)"/bkai-build/dist/*.whl
	cd /tmp && "$(CI_REPO_ROOT)/.bkai-smoke/bin/bkai-init" --help
	$(MAKE) ci-snapshot

ci-snapshot:
	@cd "$(CI_REPO_ROOT)" && $(CI_PYTHON) "$(CI_HELPER)" snapshot

ci-publish:
	@cd "$(CI_REPO_ROOT)" && $(CI_PYTHON) "$(CI_HELPER)" publish

.PHONY: image
image:
	$(CONTAINER_TOOL) build \
		--build-arg BKAI_INIT_PACKAGE=$(PACKAGE_NAME) \
		--build-arg BKAI_INIT_VERSION=$(PACKAGE_VERSION) \
		$(IMAGE_BUILD_ARGS) \
		-t $(IMAGE) ${ROOT_DIR}

.PHONY: demo-image
demo-image: image
	$(CONTAINER_TOOL) build -t $(DEMO_IMAGE) -f ${ROOT_DIR}/demo/Dockerfile ${ROOT_DIR}/demo

.PHONY: demo-test
demo-test: demo-image
	$(CONTAINER_TOOL) run --rm --read-only --tmpfs /tmp:rw,size=64m \
		$(DEMO_IMAGE) validate -f /bk-job/bkai.yaml $(if $(SPACE),--space "$(SPACE)")

.PHONY: clean
clean:
	find ${ROOT_DIR} -type f -name '*.py[co]' -delete
	find ${ROOT_DIR} -type d -name '__pycache__' -prune -exec rm -rf {} +
	rm -rf ${ROOT_DIR}/.pytest_cache ${ROOT_DIR}/.ruff_cache
	rm -rf ${ROOT_DIR}/build ${ROOT_DIR}/dist ${ROOT_DIR}/bkai_init.egg-info
	rm -rf ${ROOT_DIR}/.venv
