.PHONY: uv_dev dev trace-dev lint test test_unit watch_unit test_integration clean clean_test_integration docker_unit_lint up_dev down_dev up_deploy down_deploy
.PHONY: ci_unit_lint_clean ci_unit_lint
.PHONY: up down up_dev down_dev up_deploy down_deploy
.PHONY: docker_integration_test down_integration ci_test_integration ci_test_integration_clean
.PHONY: local_docker_integration_test

# Used by `docker compose` dev targets that use multiple yml files.
COMPOSE_DEV_FILES = -f docker-compose.yml -f docker-compose-dev.yml

help:
	@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

env uv_dev:  ## Prepare environment
	uv venv --allow-existing
	uv sync --locked

clean:  ## Clean environment
	rm -rf .venv env .cache .pytest_cache .mypy_cache .ruff_cache pyunit.xml .coverage coverage.xml
	find . | grep -E '__pycache__|\.pyc|\.pyo$\' | xargs rm -rf

dev: env  # Run dev application
	uv run python dev.py

trace-dev: env  # Run dev application with ddtrace
	set -o allexport; source .env; set +o allexport; uv run ddtrace-run python dev.py

lint: uv_dev  ## Run code linters
	uv run ty check product_staging tests
	uv run ruff check product_staging tests
	uv run ruff format product_staging tests --diff


fmt:  uv_dev ## Run code formatters
	uv run ruff check product_staging tests --fix
	uv run ruff format product_staging tests

test_unit: uv_dev  ## Run unit tests
	uv run pytest tests/unit/ \
		--cov product_staging \
		--cov-report xml \
		--cov-report term \
		--junitxml=pyunit.xml

test_integration: uv_dev  ## Run integration tests
	uv run pytest tests/integration/ \
		--cov product_staging \
		--cov-report xml \
		--cov-report term \
		--junitxml=pyunit.xml

watch_unit: uv_dev ## Run unit tests in watch mode
	uv run ptw tests/unit/

docker_unit_lint:  # Run lint and unit tests in Docker
	docker compose up \
		--build \
		--exit-code-from unit-lint \
		--abort-on-container-exit \
		--remove-orphans \
		unit-lint

down_unit_lint:  # Teardown any remaining Docker containers related to lint and unit tests
	docker compose down unit-lint --remove-orphans

ci_unit_lint: ci_unit_lint_clean  # Run lint and unit tests in CI/CD
	mkdir -p build
	chmod a+w build
	make docker_unit_lint

ci_unit_lint_clean: down_unit_lint  # Teardown lint and unit tests in CI/CD
	rm -rf build

up: up_dev  # Bring up dockerized dev service (supports hot-reload)

down:  # Bring down all docker containers
	docker compose $(COMPOSE_DEV_FILES) down

up_dev:  # Bring up dockerized dev service (supports hot-reload)
	docker compose $(COMPOSE_DEV_FILES) up \
		--detach \
		--remove-orphans \
		product_staging-dev

down_dev:  # Bring down all docker containers associated with running the dev service
	docker compose $(COMPOSE_DEV_FILES)  down product_staging-dev

up_deploy:  # Bring up dockerized deploy service
	docker compose build \
		--no-cache \
		product_staging-deploy
	docker compose $(COMPOSE_DEV_FILES) up \
		--detach \
		--remove-orphans \
		product_staging-deploy

down_deploy:  # Bring down all docker containers associated with running the deploy service
	docker compose down product_staging-deploy

docker_integration_test:  # Run integration tests in Docker
	docker compose build product_staging-deploy
	docker compose up \
		--build \
		--exit-code-from integration-test \
		--abort-on-container-exit \
		--remove-orphans \
		integration-test

down_integration: down  # Teardown any remaining Docker containers related to integration tests

ci_test_integration: ci_test_integration_clean  # Run integration tests in CI/CD
	make docker_integration_test

ci_test_integration_clean: down_integration  # Teardown integration tests in CI/CD

local_docker_integration_test:
	docker compose build product_staging-deploy
	docker compose $(COMPOSE_DEV_FILES) up \
		--build \
		--exit-code-from integration-test \
		--abort-on-container-exit \
		--remove-orphans \
		integration-test

local_docker_db_refresh:  # Get latest docker-database-image
	docker compose $(COMPOSE_DEV_FILES) down
	docker volume rm ows-product-staging_mysql_data_volume || true
	docker compose $(COMPOSE_DEV_FILES) pull mysql-db
	docker compose $(COMPOSE_DEV_FILES) up -d mysql-db
