default: help

help: # Show help for each of the Makefile recipes.
	@grep -E '^[a-zA-Z0-9 -]+:.*#'  Makefile | sort | while read -r l; do printf "\033[1;32m$$(echo $$l | cut -f 1 -d':')\033[00m:$$(echo $$l | cut -f 2- -d'#')\n"; done

build: # Compile the release CLI binary.
	@echo "[+] Building release binary"
	cargo build --release

develop: # Build and install the Python extension with maturin (debug).
	@echo "[+] Building Python extension"
	. .venv/bin/activate && maturin develop

develop-release: # Build and install the Python extension with maturin (release).
	@echo "[+] Building Python extension (release)"
	. .venv/bin/activate && maturin develop --release

lint: lint-rs lint-py # Run all linters (Rust + Python).

lint-rs: # Check Rust formatting and run clippy.
	@echo "[+] Checking Rust formatting"
	cargo fmt --check
	@echo "[+] Running clippy"
	cargo clippy -- -D warnings

lint-py: # Check Python formatting (black) and run mypy + pylint.
	@echo "[+] Checking Python formatting"
	. .venv/bin/activate && black --check python/
	@echo "[+] Running mypy"
	. .venv/bin/activate && mypy python/pyaxml/
	@echo "[+] Running pylint"
	. .venv/bin/activate && pylint python/pyaxml/

test: test-rs test-py # Run all tests (Rust + Python).

test-rs: # Run Rust integration tests.
	@echo "[+] Running Rust tests"
	cargo test

test-py: # Run Python tests (requires maturin develop first).
	@echo "[+] Running Python tests"
	. .venv/bin/activate && python3 -m pytest tests-py/ -v

install: # Install the pyaxml CLI binary and Python package into the active Python env.
	@echo "[+] Installing pyaxml binary"
	cargo install --path .
	@echo "[+] Installing pyaxml Python package"
	python3 -m pip install -e .

bump: # Bump version: make bump VERSION=x.y.z  (updates Cargo.toml; pyproject.toml and __init__.py derive from it).
	@test -n "$(VERSION)" || (echo "Usage: make bump VERSION=x.y.z" && exit 1)
	@sed -i '0,/^version = "[^"]*"/s//version = "$(VERSION)"/' Cargo.toml
	@echo "[+] Version set to $(VERSION) in Cargo.toml"

clean: # Remove build artefacts.
	@echo "[+] Cleaning"
	cargo clean

ci-local: # Run lint+test pipeline locally (Linux in Docker, Win/macOS via SSH).
	python3 scripts/ci-local.py --no-tag lint:rust lint:python test:rust test:python

ci-local-tag: # Run tag-gated build/package jobs locally; CI_COMMIT_TAG auto-detected from git.
	python3 scripts/ci-local.py \
	    build:binary:linux-x86_64 build:binary:windows-x86_64 \
	    package:wheel:linux-x86_64 package:wheel:windows-x86_64

ci-local-all: # Run every applicable job locally except release:* (need real tokens).
	python3 scripts/ci-local.py --all --skip-release

ci-local-list: # Show how each job will be routed (docker vs ssh).
	python3 scripts/ci-local.py --list --all

clean-wheels: # Remove built wheels (avoids uploading stale ones).
	rm -f target/wheels/*.whl

publish-pypi: # Upload wheels in target/wheels/ to PyPI. Requires MATURIN_PYPI_TOKEN.
	@test -f .gitlab-ci-local-variables.yml || \
	    (echo "ERROR: .gitlab-ci-local-variables.yml missing — copy from .example and add MATURIN_PYPI_TOKEN"; exit 1)
	@TAG=$$(git describe --tags --abbrev=0 2>/dev/null); \
	    test -n "$$TAG" || (echo "ERROR: no git tag found"; exit 1); \
	    ls target/wheels/*.whl >/dev/null 2>&1 || (echo "ERROR: no wheels in target/wheels/ — run 'make ci-local-tag' first"; exit 1); \
	    echo "About to upload $$(ls target/wheels/*.whl | wc -l) wheel(s) to PyPI as $$TAG"; \
	    read -p "Type the tag to confirm: " ans; \
	    test "$$ans" = "$$TAG" || (echo "Aborted"; exit 1)
	python3 scripts/ci-local.py --manual release:pypi

publish-crate: # Publish the crate to crates.io. Requires CARGO_REGISTRY_TOKEN.
	@test -f .gitlab-ci-local-variables.yml || \
	    (echo "ERROR: .gitlab-ci-local-variables.yml missing — copy from .example and add CARGO_REGISTRY_TOKEN"; exit 1)
	@TAG=$$(git describe --tags --abbrev=0 2>/dev/null); \
	    test -n "$$TAG" || (echo "ERROR: no git tag found"; exit 1); \
	    echo "About to run 'cargo publish' at $$TAG"; \
	    read -p "Type the tag to confirm: " ans; \
	    test "$$ans" = "$$TAG" || (echo "Aborted"; exit 1)
	python3 scripts/ci-local.py --manual release:crate

publish-gitlab: # Create the gitlab.com Release page with binaries+wheels as attached assets. Requires GITLAB_TOKEN.
	@test -f .gitlab-ci-local-variables.yml || \
	    (echo "ERROR: .gitlab-ci-local-variables.yml missing — copy from .example and add GITLAB_TOKEN"; exit 1)
	@TAG=$$(git describe --tags --abbrev=0 2>/dev/null); \
	    test -n "$$TAG" || (echo "ERROR: no git tag found"; exit 1); \
	    echo "About to (re)create GitLab Release $$TAG and upload assets from binaries/ + target/wheels/"; \
	    read -p "Type the tag to confirm: " ans; \
	    test "$$ans" = "$$TAG" || (echo "Aborted"; exit 1)
	python3 scripts/publish-gitlab-release.py

publish-all: clean-wheels ci-local-tag publish-pypi publish-crate publish-gitlab # Full local release: build wheels+binaries, then publish to PyPI, crates.io, and gitlab.com.
	@echo "[+] Local publish complete (PyPI + crates.io + GitLab Release)."
