.PHONY: integration-test lint format typecheck test installdeps clean

GENERATED_PROJECT := /tmp/mistral-workflows-integration-test

# run_worker blocks indefinitely on a live server connection. The worker-start
# tests only assert that discovery/start logging happens before that connect, so
# stub run_worker to return immediately and avoid hanging the pipeline.
STUB_RUN_WORKER := import asyncio; import mistralai.workflows as _w; _w.run_worker = lambda *a, **k: asyncio.sleep(0);

## CLI (mistralai-workflows-cli) development targets
lint:
	uv run ruff check .
	uv run ruff format --check .

format:
	uv run ruff format .
	uv run ruff check --fix .

typecheck:
	uv run mypy src/

test:
	uv run pytest

installdeps:
	uv sync

clean:
	rm -rf dist/ build/ *.egg-info

## Generate a project via the CLI and run integration tests
integration-test:
	rm -rf $(GENERATED_PROJECT)
	$(MAKE) _test-cli-wheel-template
	uv run mistral-workflows setup --api-key sk-test \
		-o $(dir $(GENERATED_PROJECT)) -n $(notdir $(GENERATED_PROJECT))
	$(MAKE) _test-uv-lock-generated
	$(MAKE) _test-discover
	$(MAKE) _test-start-worker
	$(MAKE) _test-start-worker-module
	$(MAKE) _test-start-worker-importlib
	$(MAKE) _test-start-examples
	$(MAKE) _test-execute-help
	$(MAKE) _test-execute-bad-json
	$(MAKE) _test-wheel-contents
	@echo ""
	@echo "All integration tests passed."

_test-cli-wheel-template:
	@echo "--- test: built CLI wheel ships the copier template"
	rm -rf dist && uv build --wheel > /dev/null
	unzip -l dist/*.whl \
		| grep -q "mistral_workflows_cli/_template/copier.yml" \
		&& echo "OK: CLI wheel contains copier.yml" \
		|| (echo "FAIL: CLI wheel is missing copier.yml" && exit 1)
	unzip -l dist/*.whl \
		| grep -q "mistral_workflows_cli/_template/template/pyproject.toml.jinja" \
		&& echo "OK: CLI wheel contains template files" \
		|| (echo "FAIL: CLI wheel is missing template files" && exit 1)

_test-uv-lock-generated:
	@echo "--- test: copier _tasks generated uv.lock"
	@test -f $(GENERATED_PROJECT)/uv.lock \
		&& echo "OK: uv.lock generated" \
		|| (echo "FAIL: uv.lock was not generated by copier _tasks" && exit 1)

_test-discover:
	@echo "--- test: workflow discovery"
	cd $(GENERATED_PROJECT) && uv run python -c \
		"from entrypoints.worker import discover_workflows; wfs = discover_workflows(); assert len(wfs) > 0, 'No workflows discovered'; print(f'OK: discovered {len(wfs)} workflow(s)')"

_test-start-worker:
	@echo "--- test: entrypoints.worker discovers workflows before connecting"
	cd $(GENERATED_PROJECT) && uv run python -c \
		"$(STUB_RUN_WORKER) import runpy; runpy.run_module('entrypoints.worker', run_name='__main__')" 2>&1 \
		| grep -q "Discovered .* workflow(s)" \
		&& echo "OK: worker discovered workflows" \
		|| (echo "FAIL: worker did not print discovery message" && exit 1)

_test-start-worker-module:
	@echo "--- test: python -m worker discovers workflows before connecting"
	cd $(GENERATED_PROJECT) && uv run python -c \
		"$(STUB_RUN_WORKER) import runpy; runpy.run_module('worker', run_name='__main__')" 2>&1 \
		| grep -q "Discovered .* workflow(s)" \
		&& echo "OK: worker module discovered workflows" \
		|| (echo "FAIL: worker module did not print discovery message" && exit 1)

_test-start-worker-importlib:
	@echo "--- test: MISTRAL_WORKER_ENTRYPOINT with importlib entrypoint script"
	cd $(GENERATED_PROJECT) && MISTRAL_WORKER_ENTRYPOINT=worker:main \
		uv run python -c "import asyncio, importlib, inspect, os; $(STUB_RUN_WORKER) \
m, f = os.environ['MISTRAL_WORKER_ENTRYPOINT'].split(':', 1); \
result = getattr(importlib.import_module(m), f)(); \
asyncio.run(result) if inspect.iscoroutine(result) else None" 2>&1 \
		| grep -q "Discovered .* workflow(s)" \
		&& echo "OK: MISTRAL_WORKER_ENTRYPOINT with importlib entrypoint script loaded and discovered workflows" \
		|| (echo "FAIL: MISTRAL_WORKER_ENTRYPOINT with importlib entrypoint script did not discover workflows" && exit 1)

_test-start-examples:
	@echo "--- test: examples.worker loads example workflows before connecting"
	cd $(GENERATED_PROJECT) && uv run python -c \
		"$(STUB_RUN_WORKER) import runpy; runpy.run_module('examples.worker', run_name='__main__')" 2>&1 \
		| grep -q "Starting worker with .* example(s)" \
		&& echo "OK: examples worker started" \
		|| (echo "FAIL: examples worker did not print start message" && exit 1)

_test-execute-help:
	@echo "--- test: entrypoints.start --help"
	cd $(GENERATED_PROJECT) && uv run python -m entrypoints.start --help > /dev/null 2>&1 \
		&& echo "OK: --help works" \
		|| (echo "FAIL: --help failed" && exit 1)

_test-execute-bad-json:
	@echo "--- test: entrypoints.start rejects invalid JSON"
	cd $(GENERATED_PROJECT) && uv run python -m entrypoints.start --workflow hello-world --input 'not-json' 2>&1 \
		| grep -q "invalid JSON" \
		&& echo "OK: bad JSON rejected" \
		|| (echo "FAIL: bad JSON not rejected" && exit 1)

_test-wheel-contents:
	@echo "--- test: built wheel ships the entrypoints package"
	cd $(GENERATED_PROJECT) && rm -rf dist && uv build --wheel > /dev/null
	cd $(GENERATED_PROJECT) && unzip -l dist/*.whl \
		| grep -q "entrypoints/worker.py" \
		&& echo "OK: wheel contains entrypoints package" \
		|| (echo "FAIL: wheel is missing the entrypoints package" && exit 1)
