## Makefile for tschm/.config-templates
# (https://github.com/tschm/.config-templates)
#
# Purpose: Developer tasks using uv/uvx (install, test, docs, marimushka, book).
# Lines with `##` after a target are parsed into help text,
# and lines starting with `##@` create section headers in the help output.
#
# Colors for pretty output in help messages
BLUE := \033[36m
BOLD := \033[1m
GREEN := \033[32m
RED := \033[31m
YELLOW := \033[33m
RESET := \033[0m

# Default goal when running `make` with no target
.DEFAULT_GOAL := help

# Declare phony targets (they don't produce files)
.PHONY: install-uv install clean test marimo marimushka book fmt deptry docs help all

UV_INSTALL_DIR := ./bin
UV_BIN := ${UV_INSTALL_DIR}/uv
UVX_BIN := ${UV_INSTALL_DIR}/uvx
MARIMO_FOLDER := book/marimo
TESTS_FOLDER := tests
SOURCE_FOLDER := src
BOOK_TITLE := Project Documentation
BOOK_SUBTITLE := Generated by minibook

export UV_NO_MODIFY_PATH := 1
export UV_VENV_CLEAR := 1

##@ Bootstrap
install-uv: ## ensure uv/uvx is installed
	# Ensure the ${UV_INSTALL_DIR} folder exists
	@mkdir -p ${UV_INSTALL_DIR}

	# Install uv/uvx only if they are not already present
	@if [ -x "${UV_INSTALL_DIR}/uv" ] && [ -x "${UV_INSTALL_DIR}/uvx" ]; then \
	  printf "${BLUE}[INFO] uv and uvx already installed in ${UV_INSTALL_DIR}, skipping.${RESET}\n"; \
	else \
	  printf "${BLUE}[INFO] Installing uv and uvx...${RESET}\n"; \
	  if ! curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR="${UV_INSTALL_DIR}" sh >/dev/null 2>&1; then \
	    printf "${RED}[ERROR] Failed to install uv${RESET}\n"; \
	    exit 1; \
	  fi; \
	fi

install-extras: ## run custom build script (if exists)
	@if [ -x ".github/scripts/build-extras.sh" ]; then \
		printf "${BLUE}[INFO] Running custom build script...${RESET}\n"; \
		./.github/scripts/build-extras.sh; \
	elif [ -f ".github/scripts/build-extras.sh" ]; then \
		printf "${BLUE}[INFO] Running custom build script...${RESET}\n"; \
		/bin/sh .github/scripts/build-extras.sh; \
	else \
		printf "${BLUE}[INFO] No custom build script found, skipping...${RESET}\n"; \
	fi

install: install-uv install-extras ## install
	# Create the virtual environment only if it doesn't exist
	@if [ ! -d ".venv" ]; then \
	  ${UV_BIN} venv --python 3.12 || { printf "${RED}[ERROR] Failed to create virtual environment${RESET}\n"; exit 1; }; \
	else \
	  printf "${BLUE}[INFO] Using existing virtual environment at .venv, skipping creation${RESET}\n"; \
	fi

	# Check if there is requirements.txt file in the tests folder
	@if [ -f "tests/requirements.txt" ]; then \
	  ${UV_BIN} pip install -r tests/requirements.txt || { printf "${RED}[ERROR] Failed to install test requirements${RESET}\n"; exit 1; }; \
	fi

	# Install the dependencies from pyproject.toml (if it exists)
	@if [ -f "pyproject.toml" ]; then \
	  printf "${BLUE}[INFO] Installing dependencies${RESET}\n"; \
	  ${UV_BIN} sync --all-extras --frozen || { printf "${RED}[ERROR] Failed to install dependencies${RESET}\n"; exit 1; }; \
	else \
	  printf "${YELLOW}[WARN] No pyproject.toml found, skipping install${RESET}\n"; \
	fi


clean: ## clean
	@printf "${BLUE}Cleaning project...${RESET}\n"
	# do not clean .env files
	@git clean -d -X -f -e .env -e '.env.*'
	@rm -rf dist build *.egg-info .coverage .pytest_cache
	@printf "${BLUE}Removing local branches with no remote counterpart...${RESET}\n"
	@git fetch --prune
	@git branch -vv \
	  | grep ': gone]' \
	  | awk '{print $1}' \
	  | xargs -r git branch -D 2>/dev/null || true

##@ Development and Testing
test: install ## run all tests
	@if [ -d ${SOURCE_FOLDER} ] && [ -d ${TESTS_FOLDER} ]; then \
	  mkdir -p _tests/html-coverage _tests/html-report; \
	  ${UV_BIN} pip install pytest pytest-cov pytest-html; \
	  ${UV_BIN} run pytest ${TESTS_FOLDER} --cov=${SOURCE_FOLDER} --cov-report=term --cov-report=html:_tests/html-coverage --html=_tests/html-report/report.html; \
	else \
	  printf "${YELLOW}[WARN] Source folder ${SOURCE_FOLDER} or tests folder ${TESTS_FOLDER} not found, skipping tests${RESET}\n"; \
	fi

marimo: install ## fire up Marimo server
	@if [ ! -d "${MARIMO_FOLDER}" ]; then \
	  printf " ${YELLOW}[WARN] Marimo folder '${MARIMO_FOLDER}' not found, skipping start${RESET}\n"; \
	else \
	  ${UV_BIN} pip install marimo; \
	  ${UV_BIN} run marimo edit "${MARIMO_FOLDER}"; \
	fi

marimushka: install ## export Marimo notebooks to HTML
	@printf "${BLUE}[INFO] Exporting notebooks from ${MARIMO_FOLDER}...${RESET}\n"
	@if [ ! -d "${MARIMO_FOLDER}" ]; then \
	  printf "${YELLOW}[WARN] Directory '${MARIMO_FOLDER}' does not exist. Skipping marimushka.${RESET}\n"; \
	else \
	  ${UV_BIN} pip install marimo; \
	  MARIMO_FOLDER="${MARIMO_FOLDER}" UV_BIN="${UV_BIN}" UVX_BIN="${UVX_BIN}" /bin/sh .github/scripts/marimushka.sh; \
	fi

deptry: install-uv ## run deptry if pyproject.toml exists
	@if [ -f "pyproject.toml" ]; then \
	  ${UVX_BIN} deptry "${SOURCE_FOLDER}"; \
	else \
	  printf "${YELLOW} No pyproject.toml found, skipping deptry${RESET}\n"; \
	fi

##@ Documentation
docs: install-uv ## create documentation with pdoc
	@if [ -d ${SOURCE_FOLDER} ]; then \
  	  ${UV_BIN} pip install pdoc; \
	  ${UV_BIN} run pdoc -o _pdoc ${SOURCE_FOLDER}/*; \
	else \
	  printf "${YELLOW}[WARN] Source folder ${SOURCE_FOLDER} not found, skipping docs${RESET}\n"; \
	fi

book: test docs marimushka ## compile the companion book
	@${UV_BIN} pip install marimo
	@/bin/sh .github/scripts/book.sh
	@${UVX_BIN} minibook --title "${BOOK_TITLE}" --subtitle "${BOOK_SUBTITLE}" --links "$$(python3 -c 'import json,sys; print(json.dumps(json.load(open("_book/links.json"))))')" --output "_book"
	@touch "_book/.nojekyll"

fmt: install-uv ## check the pre-commit hooks and the linting
	@${UVX_BIN} pre-commit run --all-files

all: fmt deptry book ## Run everything
	echo "Run fmt, deptry, test and book"

##@ Meta
help: ## Display this help message
	+@printf "$(BOLD)Usage:$(RESET)\n"
	+@printf "  make $(BLUE)<target>$(RESET)\n\n"
	+@printf "$(BOLD)Targets:$(RESET)\n"
	+@awk 'BEGIN {FS = ":.*##"; printf ""} /^[a-zA-Z_-]+:.*?##/ { printf "  $(BLUE)%-15s$(RESET) %s\n", $$1, $$2 } /^##@/ { printf "\n$(BOLD)%s$(RESET)\n", substr($$0, 5) }' $(MAKEFILE_LIST)

# debugger tools
print-% :
	@echo $* = $($*)