REQ_TAG := $(shell \
	sha256sum pyproject.toml uv.lock containers/requirements.Dockerfile 2>/dev/null \
	| sha256sum | awk '{print $$1}' \
)
REQ_IMAGE ?= harbor.daktela.com/coworkers/chatbot-client-requirements
REQ_IMG := $(REQ_IMAGE):$(REQ_TAG)
CI_COMMIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
RELEASE_TAG ?= $(CI_COMMIT_TAG)
CI_USE_PREBUILT_TOOLCHAIN ?=
COVERAGE_FAIL_UNDER ?= 100
COVERAGE_PRECISION ?= 2

ifeq ($(CI_USE_PREBUILT_TOOLCHAIN),1)
DEV_TOOL_RUN :=
else
DEV_TOOL_RUN := uv run --group dev
endif
PYTHON_RUN := $(if $(DEV_TOOL_RUN),$(DEV_TOOL_RUN) python,python)
TEST_RUN := PYTHONPATH=src$${PYTHONPATH:+:$$PYTHONPATH} $(DEV_TOOL_RUN)

.PHONY: pytest
pytest:
	$(TEST_RUN) python -m pytest

.PHONY: pytest-unit
pytest-unit:
	$(TEST_RUN) python -m pytest -m "not integration"

.PHONY: pytest-integration
pytest-integration:
	$(TEST_RUN) python -m pytest -m integration

.PHONY: coverage coverage-python
coverage:
	@set -e; \
	$(TEST_RUN) coverage erase; \
	$(TEST_RUN) coverage run --source=coworkers_client -m pytest -m "not integration"; \
	$(TEST_RUN) coverage run --append --source=coworkers_client -m pytest -m integration; \
	$(TEST_RUN) coverage xml -o coverage.xml; \
	$(TEST_RUN) coverage report --precision="$(COVERAGE_PRECISION)" --fail-under="$(COVERAGE_FAIL_UNDER)" -m

coverage-python: coverage

.PHONY: ruff
ruff:
	$(DEV_TOOL_RUN) ruff check src tests scripts

.PHONY: pyright
pyright:
	$(DEV_TOOL_RUN) pyright

.PHONY: build
build:
	$(DEV_TOOL_RUN) python -m build

.PHONY: update-version
update-version:
	$(PYTHON_RUN) scripts/bump_version.py --tag "$(RELEASE_TAG)"

.PHONY: check-wheel
check-wheel:
	@set -e; \
	wheel=$$(ls dist/*.whl); \
	$(PYTHON_RUN) -c 'import email, sys, zipfile; archive = zipfile.ZipFile(sys.argv[1]); names = set(archive.namelist()); metadata_name = next((name for name in names if name.endswith(".dist-info/METADATA")), None); assert metadata_name is not None, "missing wheel metadata"; metadata = email.message_from_string(archive.read(metadata_name).decode()); assert metadata["Name"] == "coworkers_client", "unexpected distribution name: {!r}".format(metadata["Name"]); assert "coworkers_client/__init__.py" in names, "missing coworkers_client package in wheel"' "$$wheel"; \
	tmpdir=$$(mktemp -d); \
	venv_python=$$($(PYTHON_RUN) -c 'import sys; print(sys.executable)'); \
	trap 'rm -rf "$$tmpdir"' EXIT; \
	"$$venv_python" -m venv "$$tmpdir/venv"; \
	"$$tmpdir/venv/bin/pip" install "$$wheel"; \
	"$$tmpdir/venv/bin/python" -c "import coworkers_client"

.PHONY: check-dist
check-dist:
	$(PYTHON_RUN) -m twine check dist/*.whl dist/*.tar.gz

.PHONY: publish
publish:
	$(PYTHON_RUN) -m twine upload dist/*.whl dist/*.tar.gz

.PHONY: release
release: clean update-version build check-wheel check-dist publish

.PHONY: clean
clean:
	rm -rf build dist src/*.egg-info

.PHONY: compute-req-tag
compute-req-tag:
	@echo "REQ_TAG=$(REQ_TAG)" > req.env
	@echo "Wrote req.env (REQ_TAG=$(REQ_TAG))"

.PHONY: ci-build-requirements
ci-build-requirements:
	@set -e; \
	image="$(REQ_IMG)"; \
	echo "Requirements image: $$image"; \
	echo "Branch: $(CI_COMMIT_BRANCH)"; \
	if docker manifest inspect "$$image" >/dev/null 2>&1; then \
		echo "Image already exists in registry - skipping build"; \
	else \
		echo "Image missing -> building & pushing..."; \
		docker build . -f containers/requirements.Dockerfile -t "$$image"; \
		docker push "$$image"; \
	fi
