.PHONY: help setup clean lint test pre-commit commit build install-dist bump-version tag publish

.DEFAULT_GOAL := help

PYTHON ?= python3
VENV := .venv
BIN := $(VENV)/bin
PIP := $(BIN)/pip
PYTHON_BIN := $(BIN)/python
PYTEST := $(BIN)/pytest
RUFF := $(BIN)/ruff
BLACK := $(BIN)/black
BUILD_TOOL := $(PYTHON_BIN) -m build
TWINE := $(BIN)/twine
HATCH := $(BIN)/hatch

help: ## Show available make targets.
	@grep -E '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS=":.*## "}; {printf "%-18s %s\n", $$1, $$2}'

.venv/pyvenv.cfg: pyproject.toml ## Create virtualenv and install dev dependencies (once).
	$(PYTHON) -m venv $(VENV)
	$(PIP) install --upgrade pip
	$(PIP) install -e ".[dev]"
	touch $@

install: .venv/pyvenv.cfg ## Ensure virtualenv with dev dependencies.

setup: install ## Alias for install target.
	@echo "Virtualenv ready at $(VENV)"

clean: ## Remove build artifacts and virtual environment.
	rm -rf $(VENV) build dist .ruff_cache .pytest_cache .mypy_cache .coverage htmlcov

lint: install ## Format and lint code
	$(RUFF) format src tests
	$(RUFF) check src tests --fix --unsafe-fixes

test: lint ## Run test suite.
	$(PYTEST)

pre-commit: test ## Run linting, tests, and ensure clean working tree.
	@git diff --exit-code || (echo "Error: unstaged changes present."; exit 1)

commit: pre-commit ## Commit tracked changes with Conventional Commit message m="type: description".
	@: $${m?Commit message (m="...") is required}
	git status --short
	git commit -am "$$m"

build: lint test ## Build source and wheel distributions.
	$(BUILD_TOOL)

install-dist: build ## Install the built wheel into the virtualenv.
	$(PIP) install dist/*.whl

part ?= patch

bump-version: test ## Bump project version with hatch. Use part=patch|minor|major (default: patch).
	$(HATCH) version $(part)

tag: install ## Create annotated git tag from current pyproject version.
	@version=$$($(PYTHON_BIN) -c "import pathlib; print(pathlib.Path('src/rector/VERSION').read_text().strip())"); \
		git tag -a "v$$version" -m "chore: release v$$version"
		git push origin "v$$version"

publish: build ## Publish the package to PyPI using Twine.
	$(TWINE) upload dist/*
	curl https://pypi.org/pypi/rector/json  | jq '.releases | with_entries({key, value: (.value[1] as $v1 | .value[0] | {upload_time_iso_8601, size, downloads, dist: .url, source: $v1.url})})'