# This ensures that we can call `make <target>` even if `<target>` exists as a file or
# directory.
.PHONY: help docs install install-frontend install-vercel leaderboards force-leaderboards

# Exports all variables defined in the makefile available to scripts
.EXPORT_ALL_VARIABLES:

# Create .env file if it does not already exist
ifeq (,$(wildcard .env))
  $(shell touch .env)
endif

# Includes environment variables from the .env file
include .env

# Set gRPC environment variables, which prevents some errors with the `grpcio` package
export GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1
export GRPC_PYTHON_BUILD_SYSTEM_ZLIB=1

# Set the PATH env var used by cargo and uv
export PATH := ${HOME}/.local/bin:${HOME}/.cargo/bin:$(PATH)

# Set the shell to bash, enabling the use of `source` statements
SHELL := /bin/bash

help:
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

install: ## Install dependencies
	@echo "Installing the 'EuroEval' project..."
	@$(MAKE) --quiet install-rust
	@$(MAKE) --quiet install-uv
	@$(MAKE) --quiet install-dependencies
	@$(MAKE) --quiet setup-environment-variables
	@$(MAKE) --quiet install-frontend
	@$(MAKE) --quiet install-vercel
	@echo "Installed the 'EuroEval' project."

install-rust:
	@if [ "$(shell which rustup)" = "" ]; then \
		curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y; \
		echo "Installed Rust."; \
	fi

install-uv:
	@if [ "$(shell which uv)" = "" ]; then \
		curl -LsSf https://astral.sh/uv/install.sh | sh; \
			echo "Installed uv."; \
		else \
			echo "Updating uv..."; \
			uv self update || true; \
	fi

install-dependencies:
	@uv python install 3.12
	@uv sync --all-extras --all-groups --python 3.12

setup-environment-variables:
	@uv run python src/scripts/fix_dot_env_file.py

setup-environment-variables-non-interactive:
	@uv run python src/scripts/fix_dot_env_file.py --non-interactive

install-frontend: ## Install frontend dependencies
	@echo "Installing frontend dependencies..."
	@npm install
	@echo "Installed frontend dependencies."

install-vercel:
	@if [ "$(shell which vercel)" = "" ]; then \
		npm install -g vercel; \
		echo "Installed Vercel CLI."; \
	fi

install-pre-commit:
	@uv run pre-commit install
	@uv run pre-commit autoupdate

test:  ## Run tests
	@uv run pytest && uv run readme-cov && rm .coverage*

frontend:  ## Build and deploy the frontend
	@vercel build --prod 2>&1 | grep -v "^WARNING!" && vercel deploy --prebuilt --prod

leaderboards:  ## Collect finished evaluation results and regenerate leaderboards
	@uv run python src/scripts/collect_evaluation_results.py

force-leaderboards:
	@uv run python src/scripts/collect_evaluation_results.py --force

tree:  ## Print directory tree
	@tree -a --gitignore -I .git .

check:  ## Lint, format, and type-check the code
	@git add . && uv run pre-commit run --all-files
	@if command -v llama-server >/dev/null 2>&1 && pgrep -x llama-server >/dev/null; then \
		echo "Running Slopo code duplication detection..."; \
		export LITELLM_DROP_PARAMS=true; \
		uv run slopo index 2>&1 | grep -E "Indexed|unchanged|removed" || true; \
		uv run slopo embed 2>&1 || true; \
		ANALYSIS_OUTPUT=$$(uv run slopo analyze 2>&1); \
		echo "$$ANALYSIS_OUTPUT" | grep -E "Exact copies|Similarity ratio" || true; \
		DUPLICATE_COUNT=$$(echo "$$ANALYSIS_OUTPUT" | grep "Similarity ratio (including exact copies)" | sed -E 's/.*\(([0-9]+)\/.*/\1/'); \
		if [ "$$DUPLICATE_COUNT" -gt 0 ] 2>/dev/null; then \
			RATIO=$$(echo "$$ANALYSIS_OUTPUT" | grep "Similarity ratio (including exact copies)" | sed -E 's/.*: ([0-9.]+%).*/\1/'); \
			echo ""; \
			echo "❌ Slopo failed: duplicate code detected"; \
			printf "   Duplicate units: %s\n" "$$DUPLICATE_COUNT"; \
			printf "   Similarity ratio: %s\n" "$$RATIO"; \
			echo "   Full report: .slopo/report/index.md"; \
			echo "   To ignore irrelevant duplicates, add their cluster hashes to .slopo/slopo.ignore.txt"; \
			echo ""; \
			exit 1; \
		fi; \
	else \
		echo "Slopo skipped (llama.cpp server not running)"; \
	fi

bump-major:
	@uv run python -m src.scripts.versioning --major
	@echo "Bumped major version!"

bump-minor:
	@uv run python -m src.scripts.versioning --minor
	@echo "Bumped minor version!"

bump-patch:
	@uv run python -m src.scripts.versioning --patch
	@echo "Bumped patch version!"

add-dev-version:
	@if [ $$(uname) = "Darwin" ]; then \
		sed -i '' 's/^version = "\(.*\)"/version = "\1.dev"/' pyproject.toml; \
	else \
		sed -i 's/^version = "\(.*\)"/version = "\1.dev"/' pyproject.toml; \
	fi
	@uv lock
	@git add pyproject.toml uv.lock
	@git commit -m "chore: Add '.dev' suffix to the version number"
	@git push
	@echo "Added '.dev' suffix to the version number."

publish:
	@if [ ${PYPI_API_TOKEN} = "" ]; then \
		echo "No PyPI API token specified in the '.env' file, so cannot publish."; \
	else \
		echo "Publishing to PyPI..."; \
		$(MAKE) --quiet publish-euroeval \
			&& $(MAKE) --quiet publish-scandeval \
			&& $(MAKE) --quiet add-dev-version \
			&& $(MAKE) --quiet frontend \
			&& echo "Published!"; \
	fi

publish-euroeval:
	@rm -rf build/ dist/
	@uv build
	@uv publish --username "__token__" --password ${EUROEVAL_PYPI_API_TOKEN}

publish-scandeval:
	@if [ $$(uname) = "Darwin" ]; then \
		sed -i '' 's/^name = "EuroEval"/name = "ScandEval"/' pyproject.toml; \
	else \
		sed -i 's/^name = "EuroEval"/name = "ScandEval"/' pyproject.toml; \
	fi
	@mv src/euroeval src/scandeval
	@rm -rf build/ dist/
	@uv build
	@uv publish --username "__token__" --password ${SCANDEVAL_PYPI_API_TOKEN}
	@if [ $$(uname) = "Darwin" ]; then \
		sed -i '' 's/^name = "ScandEval"/name = "EuroEval"/' pyproject.toml; \
	else \
		sed -i 's/^name = "ScandEval"/name = "EuroEval"/' pyproject.toml; \
	fi
	@mv src/scandeval src/euroeval

publish-major: install check bump-major publish  ## Publish a major version

publish-minor: install check bump-minor publish  ## Publish a minor version

publish-patch: install check bump-patch publish  ## Publish a patch version

loc: ## Count the number of lines of code in the project
	@git ls-files | grep '\.py' | xargs wc -l | tail -n 1
