SHELL := bash

version := 0.0.1

src.python := $(shell find ./src -type f -name "*.py" || :)
test.python := $(shell find ./tests -type f -name "*.py" || :)
src.python.pyc := $(shell find . -type f -name "*.pyc")
cache.dir := $(shell find . -type d -name __pycache__)
checkpoint.dir := $(shell find . -type d -name .ipynb_checkpoints)
mypy.cache.dir := $(shell find . -type d -name ".mypy_cache")
pytest.cache.dir := $(shell find . -type d -name ".pytest_cache")

notebooks := $(shell find ./notebooks -type f -name "*.ipynb" || :)

deployments.dir := deployment
uv.project.enviroment := .venv
dist.dir := dist

build.wheel := $(dist.dir)/mailsight-$(version).tar.gz

docker.image := mailsight_base:$(version)
docker.image.deploy := mailsight:$(version)

deployments.instances = $(shell find $(deployments.dir) -type d -mindepth 1 -maxdepth 2)

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

#######################
#     Documentation   #
#######################
# Full MkDocs site is optional: add mkdocs.yml (and sync --group docs) before enabling targets here.

#######################
#      Setup & Build   #
#######################

.PHONY: install
install: setup ## Installing dependencies
	uv sync 

.PHONY: setup
setup: ## Setup the project.
	uv venv $(uv.project.enviroment)

#######################
#    Containerization #
#######################

.PHONY: build-base
build-base: ## Build the base docker image for development
	docker build -f deployment/Dockerfile.base -t $(docker.image) .

.PHONY: build-deployment
build-deployment: clean ## build base deployment image
	DOCKER_BUILDKIT=1 docker build -f deployment/Dockerfile.deploy -t $(docker.image.deploy) .

push-deployment: build-deployment ## push base deploy image to registry
	docker tag $(docker.image.deploy) $(docker.image.registry)/$(docker.image.deploy)
	docker push $(docker.image.registry)/$(docker.image.deploy)

.PHONY: test-deployment
test-container: ## test container in base image with local project
	docker run --rm --volume .:/app --volume /app/.venv $(docker.image) make test

.PHONY: join-dev 
join-dev: build-base ## mount local project into the image for development in container
	docker run --rm -it --volume .:/app --volume /app/.venv  $(docker.image) /bin/sh

$(build.wheel): $(src.python) ## Build wheels for distribution.
	uv build -o $(dist.dir)

build: $(build.wheel) ## Build the distribution wheel.

#######################
#     Testing & QA      #
#######################
test: $(test.python) $(src.python)  clean ## Run tests
	uv run pytest -c=config/pytest.ini $(test.python)

# Quality Checks

.PHONY: pre-commit
pre-commit: check-format lint check-types


.PHONY: check-types
check-types: ## Run mypy to check type definitions.
	uv run mypy --config=config/mypy.ini $(src.python) $(test.python)


.PHONY: check-format
check-format: ## Check ruff format
	uv run ruff format --check --config=config/ruff.toml $(src.python) $(test.python)


.PHONY: lint
lint: ## Run ruff Code Linter
	uv run ruff check --verbose --config=config/ruff.toml $(src.python) $(test.python)

# Automated Quality fixes

.PHONY: lint-fix
lint-fix: ## Fix ruff Lint issues
	uv run ruff check --fix --config=config/ruff.toml $(src.python) $(test.python)


.PHONY: format
format:  ## Run ruff format (including sorting of imports)
	uv run ruff check --select I --config=config/ruff.toml --fix
	uv run ruff format --config=config/ruff.toml $(src.python) $(test.python)


# ipykernel
.PHONY: jupyter	
jupyter: ## Create a jupyter kernel
	uv run python -m ipykernel install --user --name=mailsight

.PHONY: clean-notebooks
clean-notebooks: ## Clean notebooks
	uv run nb-clean clean $(notebooks) --remove-all-notebook-metadata --remove-empty-cells

#######################
#     Maintenance       #
#######################
.PHONY: clean
clean: clean-test ## Remove all build artifacts.
	rm -f docs/modules.rst
	rm -rf dist/
	rm -f $(src.python.pyc)
	rm -rf site/
	

.PHONY: clean-test
clean-test: ## Remove test and coverage artifacts.
	rm -fr .tox/
	rm -fr .coverage*
	rm -fr htmlcov/
	rm -rf junit.xml
	rm -rf .ruff_cache
	rm -rf $(pytest.cache.dir)
	rm -rf $(cache.dir)
	rm -rf $(checkpoint.dir)
	rm -rf $(mypy.cache.dir)
	rm -rf interrogate_badge.svg
	rm -rf maintain.svg

.PHONY: vscode
vscode: ## Setup vscode
	cp config/vscode/* .vscode/

#######################
#      Versioning       #
#######################

.PHONY: bump-patch
bump-patch: ## Bump the patch version (_._.X) everywhere.
	@$(call i, Bumping the patch number)
	uv run bump2version patch --allow-dirty --verbose --config-file config/.bumpversion.cfg

.PHONY: bump-minor
bump-minor: ## Bump the minor version (_.X._) everywhere.
	@$(call i, Bumping the minor number)
	uv run bump2version minor --allow-dirty --verbose --config-file config/.bumpversion.cfg

.PHONY: bump-major
bump-major: ## Bump the major version (X._._) everywhere.
	@$(call i, Bumping the major number)
	uv run bump2version major --allow-dirty --verbose --config-file config/.bumpversion.cfg

.PHONY: bump-release
bump-release: ## Convert the version into a release variant (_._._).
	@$(call i, Converting to release)
	uv run bump2version release --allow-dirty --verbose --config-file config/.bumpversion.cfg

.PHONY: bump-dev
bump-dev: ## Convert the version into a dev variant (_._._-dev__).
	@$(call i, Converting to dev)
	uv run bump2version dev --allow-dirty --verbose --config-file config/.bumpversion.cfg

.PHONY: bump-build
bump-build: ## Bump the build number (_._._-____XX) everywhere.
	@$(call i, Bumbing the build number)
	uv run bump2version build --allow-dirty --verbose --config-file config/.bumpversion.cfg
