FRONTEND_SOURCES := $(shell find frontend/src frontend/css -type f)

all: src/fava/static/app.js

# Compile the frontend.
src/fava/static/app.js: $(FRONTEND_SOURCES) frontend/build.ts frontend/node_modules
	cd frontend; npm run build

# Install the frontend node_modules dependencies.
frontend/node_modules: frontend/package-lock.json
	cd frontend; npm install --no-progress
	touch -m frontend/node_modules

# Create and sync a dev environment.
.PHONY: dev
dev: .venv
.venv: uv.lock pyproject.toml
	uv sync
	uv run pre-commit install
	touch -m .venv

# Build the frontend in watch mode.
.PHONY: watch
watch: .venv frontend/node_modules
	uv run watchfiles make frontend

# Remove the generated frontend and translations in addition to mostlyclean (see below).
.PHONY: clean
clean: mostlyclean
	find src/fava/static ! -name 'favicon.ico' -type f -exec rm -f {} +
	find src/fava/translations -name '*.mo' -delete
	rm -rf src/fava.egg-info
	rm -rf src/fava/translations/messages.pot

# Remove node_modules, caches, .tox, etc.
.PHONY: mostlyclean
mostlyclean:
	rm -rf .*cache
	rm -rf .eggs
	rm -rf .tox
	rm -rf .venv
	rm -rf build
	rm -rf dist
	rm -rf docs/api
	rm -rf htmlcov
	rm -rf frontend/node_modules
	find . -type f -name '*.py[c0]' -delete
	find . -type d -name "__pycache__" -delete

# Run linters.
.PHONY: lint
lint: frontend/node_modules ty
	uv run pre-commit run -v -a
	cd frontend; npm exec tsc
	cd frontend; npm exec svelte-check

# Run mypy for Python type-checking.
.PHONY: mypy
mypy:
	uv run --no-dev --group types mypy

# Run ty for Python type-checking.
.PHONY: ty
ty:
	uv run --no-dev --group types ty check --error-on-warning

# Run tests.
.PHONY: test test-js test-py test-py-old-deps
test: test-js test-py
test-js: frontend/node_modules
	cd frontend; npm run test
test-py:
	uv run --no-dev --group test pytest --cov=fava --cov-report=term-missing:skip-covered --cov-report=html --cov-fail-under=100
test-py-old-deps:
	uv run --no-project --isolated --with-editable=. --with-requirements=constraints-old.txt pytest --snapshot-ignore
test-py-typeguard:
	uv run --no-dev --group test pytest --typeguard-fixtures

# Update the snapshot files generated by the snapshot tests.
.PHONY: update-snapshots
update-snapshots:
	uv run pytest --snapshot-update --snapshot-clean
	uv run pre-commit run -a biome-check

# Update the constraints file for Python dependencies
.PHONY: update-constraints
update-constraints:
	uv lock --upgrade
	uv pip compile --quiet --extra excel --group old-deps --resolution=lowest --python-version 3.10 --upgrade --output-file constraints-old.txt pyproject.toml

# Update the frontend dependencies.
.PHONY: update-frontend-deps
update-frontend-deps:
	-cd frontend; npm outdated
	cd frontend; npm update
	cd frontend; npm run sync-pre-commit
	touch -m frontend/node_modules

# Update the tree-sitter-beancount wasm build.
.PHONY: update-tree-sitter-beancount
update-tree-sitter-beancount:
	curl -L -o frontend/src/codemirror/tree-sitter-beancount.wasm https://github.com/yagebu/tree-sitter-beancount/releases/download/v0.0.3/tree-sitter-beancount.wasm

# Update pre-commit hooks
.PHONY: update-precommit
update-precommit:
	uv run pre-commit autoupdate

# Update github actions action versions.
.PHONY: update-github-actions
update-github-actions:
	uvx gha-update
	uvx zizmor .github/workflows/*.yml

# Update frontend deps, Python deps and pre-commit
.PHONY: update
update: update-constraints update-frontend-deps update-precommit update-github-actions

# Build the website
.PHONY: docs
docs:
	uv run --no-dev --group docs docs/generate.py
	uv run --no-dev --group docs sphinx-build -b html docs build/docs

# Run fava for the example files.
.PHONY: run-example
run-example:
	@xdg-open http://localhost:3333
	BEANCOUNT_FILE= fava -p 3333 --debug tests/data/*.beancount

# Generate the bql-grammar json file used by the frontend.
.PHONY: bql-grammar
bql-grammar: .venv contrib/scripts.py
	uv run --group scripts contrib/scripts.py generate-bql-grammar-json
	-uv run pre-commit run --files frontend/src/codemirror/bql-grammar.ts

# Build the distribution (sdist and wheel).
.PHONY: dist
dist:
	rm -f dist/*{.tar.gz,.whl}
	uv build

# Build the bql-grammar and update translations with POEditor.com
.PHONY: before-release
before-release: bql-grammar translations-push translations-fetch

# Extract translation strings.
.PHONY: translations-extract
translations-extract: .venv
	uv run pybabel extract -F src/fava/translations/babel.conf -o src/fava/translations/messages.pot .

# Extract translation strings and upload them to POEditor.com.
# Requires the environment variable POEDITOR_TOKEN to be set to an API token
# for POEditor.
.PHONY: translations-push
translations-push: .venv translations-extract
	uv run --group scripts contrib/scripts.py upload-translations

# Download translations from POEditor.com. (also requires POEDITOR_TOKEN)
.PHONY: translations-fetch
translations-fetch: .venv
	uv run --group scripts contrib/scripts.py download-translations

# Create a binary using pyinstaller
dist/fava: src/fava/static/app.js
	uv run --no-project --isolated --with=. --with=pyinstaller pyinstaller --clean --noconfirm contrib/pyinstaller_spec.spec
	dist/fava --version
