.PHONY: help fetch-spec sync-version bump-sdk-version patch-spec generate regen check-drift check-release lint test test-integration test-integration-writes clean

SPEC        := openapi/swagger.json
PATCHED     := build/swagger.patched.json
SPEC_URL    := https://insightfactory-dev.insightfactory.ai/swagger/v1/swagger.json
# Authoritative generator pin. openapitools.json carries a copy because the npx
# wrapper writes one, but OPENAPI_GENERATOR_VERSION overrides it, so this wins.
GEN_VERSION := 7.24.0
GEN_OUT     := build/gen
PKG         := src/insightfactory_sdk

# The spec's info.x-release-code (3-part, prerelease suffix stripped) is the
# API prefix of the version, e.g. the `8.0.6` in `8.0.6.1`; nobody hand-bumps
# it. The trailing SDK revision *is* hand-bumped -- `make bump-sdk-version`
# -- for a change that touches the wheel but not the API (generator upgrade,
# patch_spec.py fix, packaging change). See tools/sync_version.py for why the
# version needs both.
VERSION := $(shell python3 tools/sync_version.py --print $(SPEC))

help:
	@grep -hE '^[a-z-]+:.*?## ' $(MAKEFILE_LIST) | sed 's/:.*## /\t/'

fetch-spec: ## Re-download the OpenAPI spec from the dev factory
	curl -fsSL -o $(SPEC) $(SPEC_URL)

sync-version: ## Write pyproject.toml's version from the spec's x-release-code
	python3 tools/sync_version.py $(SPEC)
#	Keeps uv.lock's own pin on this package in step: `uv sync --locked` (what CI
#	runs) hard-fails on a stale lock, with an error that doesn't mention version.
	uv lock

bump-sdk-version: ## Bump the SDK revision for a client change with no API release-code move
	python3 tools/sync_version.py --bump $(SPEC)
	uv lock

patch-spec: ## Assign operationIds so generated methods get readable names
	@mkdir -p build
	python3 tools/patch_spec.py $(SPEC) $(PATCHED) tools/operation_id_overrides.json

generate: sync-version patch-spec ## Regenerate src/insightfactory_sdk from the patched spec
	@rm -rf $(GEN_OUT)
	OPENAPI_GENERATOR_VERSION=$(GEN_VERSION) npx --yes @openapitools/openapi-generator-cli generate \
		-i $(PATCHED) -g python -o $(GEN_OUT) \
		--library httpx \
		--additional-properties=packageName=insightfactory_sdk,projectName=insightfactory-sdk,packageVersion=$(VERSION),supportHttpxSync=true
#	Only the package tree is copied in. pyproject.toml, README and CI stay hand-written,
#	so there is nothing for the generator to clobber and no .openapi-generator-ignore to keep
#	in sync. --delete removes endpoints that no longer exist in the spec.
	rsync -a --delete $(GEN_OUT)/insightfactory_sdk/ $(PKG)/

regen: fetch-spec generate ## Fetch the latest spec and regenerate

check-drift: ## Fail if the committed SDK or version is stale relative to the spec (CI)
	@$(MAKE) generate
#	`git diff` reports tracked files only, so a brand-new generated file (the case
#	this job exists for -- a spec adding an endpoint or model) is invisible to it.
#	`git status --porcelain` sees untracked files too. It honours .gitignore, so
#	keep generated paths out of the ignore rules.
#	pyproject.toml and uv.lock are included because `generate` runs `sync-version`
#	first: a hand-edited or missed version bump, or a lockfile that didn't follow
#	it, shows up here exactly like a stale generated file does.
	@test -z "$$(git status --porcelain -- $(PKG) pyproject.toml uv.lock)" \
		|| (git status --short -- $(PKG) pyproject.toml uv.lock; printf '\n%s\n' "src/insightfactory_sdk, pyproject.toml or uv.lock is out of date; run 'make generate' and commit." && exit 1)

check-release: ## Require a CHANGELOG entry and a version bump (BASE=origin/main)
	python3 tools/check_release.py $(BASE)

lint: ## Match what CI runs
	uv run ruff check .
	uv run ruff format --check --diff .
#	No path argument: an explicit one overrides `files` in pyproject.toml, which is
#	how tools/ and tests/ ended up configured for type checking but never checked.
	uv run mypy

test: ## Offline tests only -- what CI runs
	uv run pytest -v

# The token is substituted at call time and never stored: `if-cli token` prints a
# valid one and refreshes it transparently. This build of if-cli has no
# `config get`, so the host comes from the profile listing.
IF_PROFILE ?= foundry-dev
IF_HOST = $(shell if-cli profiles 2>/dev/null | awk '$$1=="$(IF_PROFILE)"{print $$2}')

test-integration: ## Live read-only tests against IF_PROFILE (default foundry-dev)
	@test -n "$(IF_HOST)" || { echo "no host for profile '$(IF_PROFILE)'; run: if-cli login -p $(IF_PROFILE)"; exit 1; }
	IF_HOST="$(IF_HOST)" IF_TOKEN="$$(if-cli token -p $(IF_PROFILE))" uv run pytest tests/integration -v

test-integration-writes: ## Live tests including write paths (mutates a scratch resource)
	@test -n "$(IF_HOST)" || { echo "no host for profile '$(IF_PROFILE)'; run: if-cli login -p $(IF_PROFILE)"; exit 1; }
	IF_HOST="$(IF_HOST)" IF_TOKEN="$$(if-cli token -p $(IF_PROFILE))" IF_ALLOW_WRITES=1 uv run pytest tests/integration -v

clean:
	rm -rf build dist .pytest_cache .mypy_cache .ruff_cache
