GOPRIVATE:="github.com/tidbcloud/*"
MAKEFILE_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
# Prefer installed buf binary (e.g. from CI buf-action). You can still override:
# make BUF='go run github.com/bufbuild/buf/cmd/buf@v1' <target>
BUF?=buf
BUF_BIN?=$(firstword $(BUF))
BUF_VERSION?=1.66.0

BREAKING_CHANGE_COMPARE_BRANCH=release-v0.79
NEXTGEN_V1BETA2_SWAGGER_DIR=tidb_cloud_open_api/nextgen/v1beta2
NEXTGEN_V1BETA2_SWAGGER_MERGE_TEMPLATE=buf.gen.swagger.nextgen.v1beta2.merge.yaml
NEXTGEN_V1BETA2_SWAGGER_MERGE_TMP=nextgen_v1beta2_tag_filter_tmp.swagger.json
NEXTGEN_V1BETA2_SWAGGER_TAG_FILTER_SCRIPT=filter_swagger_by_tag.jq
NEXTGEN_V1BETA2_SWAGGER_MERGED_OUTPUT?=$(NEXTGEN_V1BETA2_SWAGGER_DIR)/merged.swagger.json
NEXTGEN_V1BETA2_SWAGGER_PUBLIC_OUTPUT?=$(NEXTGEN_V1BETA2_SWAGGER_DIR)/public.swagger.json
NEXTGEN_V1BETA2_SWAGGER_PREVIEW_PAGE?=$(NEXTGEN_V1BETA2_SWAGGER_DIR)/public.swagger.html
SWAGGER_PREVIEW_PORT?=18080

default: dev

# Every target that writes a committed artifact, in dependency order.
# Run this after changing any .proto or any //go:generate input.
#
# There is no correct subset to run by hand: `generate-buf` produces the .pb.go
# from the protos, and `generate` (go generate ./...) then rewrites enum String()
# methods via cmd/rewrite_enum_stringer so they honour the datatype.v1 name
# option. Running only the first leaves those enums silently reporting protobuf
# default names; running neither leaves generated code stale against the protos.
# Consumers compile this module straight from the working tree through
# `replace ... => ../api`, so whatever you leave here is what they build.
.PHONY: gen
gen: fmt-buf generate-buf generate generate-nextgen-v1beta2-swagger-public mod

# gen plus the read-only gates. The gates only read .proto files, which nothing
# after fmt-buf modifies, so running them after generation is equivalent.
.PHONY: dev
dev: gen lint-buf lint-gapi fmt test lint-buf-breaking

.PHONY: mod
mod:
	GOPRIVATE=$(GOPRIVATE) go mod tidy
	GOPRIVATE=$(GOPRIVATE) go mod download

.PHONY: generate
generate:
	GOPRIVATE=$(GOPRIVATE) go generate ./...

.PHONY: generate-buf
generate-buf: check-buf-version
	cd spec && $(BUF) dep update && $(BUF) dep prune && $(BUF) generate

.PHONY: generate-nextgen-v1beta2-swagger-merge-all
generate-nextgen-v1beta2-swagger-merge-all: check-buf-version
	cd spec && $(BUF) generate --template $(NEXTGEN_V1BETA2_SWAGGER_MERGE_TEMPLATE) --path $(NEXTGEN_V1BETA2_SWAGGER_DIR)
	cd spec && mv -f $(NEXTGEN_V1BETA2_SWAGGER_MERGE_TMP) $(NEXTGEN_V1BETA2_SWAGGER_MERGED_OUTPUT)

.PHONY: generate-nextgen-v1beta2-swagger-public
generate-nextgen-v1beta2-swagger-public: check-buf-version
	cd spec && $(BUF) generate --template $(NEXTGEN_V1BETA2_SWAGGER_MERGE_TEMPLATE) --path $(NEXTGEN_V1BETA2_SWAGGER_DIR)
	cd spec && jq --arg tags "public" -f $(NEXTGEN_V1BETA2_SWAGGER_TAG_FILTER_SCRIPT) $(NEXTGEN_V1BETA2_SWAGGER_MERGE_TMP) > $(NEXTGEN_V1BETA2_SWAGGER_PUBLIC_OUTPUT)
	cd spec && rm -f $(NEXTGEN_V1BETA2_SWAGGER_MERGE_TMP)

.PHONY: preview-nextgen-v1beta2-swagger-public
preview-nextgen-v1beta2-swagger-public:
	preview_file="$(MAKEFILE_DIR)/spec/$(NEXTGEN_V1BETA2_SWAGGER_PREVIEW_PAGE)"; \
	if [ ! -f "$$preview_file" ]; then \
		echo "Missing preview page: $$preview_file"; \
		exit 1; \
	fi; \
	echo "Open in browser: http://127.0.0.1:$(SWAGGER_PREVIEW_PORT)/$(NEXTGEN_V1BETA2_SWAGGER_PREVIEW_PAGE)"; \
	echo "Serving from $(MAKEFILE_DIR)/spec (Ctrl+C to stop)"; \
	cd "$(MAKEFILE_DIR)/spec" && python3 -m http.server $(SWAGGER_PREVIEW_PORT)

.PHONY: fmt
fmt:
	GOPRIVATE=$(GOPRIVATE) go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11 run --config $(MAKEFILE_DIR)/../.golangci.yml --fix

.PHONY: fmt-buf
fmt-buf: check-buf-version
	cd spec && $(BUF) format -w

.PHONY: lint
lint:
	# There is no need to skip autogenerated go files explicitly, golangci-lint confidently recognize autogenerated files
	GOPRIVATE=$(GOPRIVATE) go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11 run --config $(MAKEFILE_DIR)/../.golangci.yml

.PHONY: lint-buf
lint-buf: check-buf-version
	cd spec && $(BUF) lint

.PHONY: lint-buf-breaking
lint-buf-breaking: check-buf-version
	cd spec && $(BUF) breaking --against 'ssh://git@github.com/tidbcloud/tidb-management-service.git#branch=$(BREAKING_CHANGE_COMPARE_BRANCH),subdir=api/spec'

.PHONY: lint-gapi
lint-gapi: check-buf-version
	# Build the lint dependency first.
	cd spec && $(BUF) build --as-file-descriptor-set --path tidb_cloud_open_api -o tidb_cloud_open_api/file-descriptor-set.binpb

	cd spec && go run github.com/googleapis/api-linter/cmd/api-linter@v1.69 \
		--descriptor-set-in "tidb_cloud_open_api/file-descriptor-set.binpb" \
		--config "tidb_cloud_open_api/.api-linter.yaml" \
		--set-exit-status \
		"tidb_cloud_open_api/common/v1beta1/clusterstate.proto" \
		"tidb_cloud_open_api/dedicated/v1beta1/services.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/tidb.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/region.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/resource_pool.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/backup.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/byoc_vpc_peering.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/common.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/private_endpoint.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/public_connection_setting.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/database_auditlog.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/cmek.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/log_redaction_policy.proto" \
		"tidb_cloud_open_api/nextgen/v1beta2/rcu_quota.proto" \
		"tidb_cloud_open_api/fs/v1beta2/services.proto"
#		"tidb_cloud_open_api/common/v1beta1/service_plan.proto" \
#		"tidb_cloud_open_api/common/v1beta1/region.proto" \
#		"tidb_cloud_open_api/dedicated/v1beta1/resources.proto" \
#		"tidb_cloud_open_api/serverless/v1beta1/services.proto" \

.PHONY: test
test:
	GOPRIVATE=$(GOPRIVATE) go run gotest.tools/gotestsum@latest --format=testname -- -v -race -failfast -shuffle=on -coverprofile=$(MAKEFILE_DIR)/../coverage.api.txt ./...

.PHONY: build
build:
	#echo "not implemented"

.PHONY: vet
vet:
	GOPRIVATE=$(GOPRIVATE) go vet ./...

.PHONY: check-buf-version
check-buf-version:
	@if ! command -v $(BUF_BIN) >/dev/null 2>&1; then \
		echo "buf is not installed. Install buf v$(BUF_VERSION) first."; \
		exit 1; \
	fi
	@buf_version="$$( $(BUF) --version | awk '{print $$1}' | sed 's/^v//' )"; \
	if [ "$$buf_version" != "$(BUF_VERSION)" ]; then \
		echo "buf version mismatch: expected $(BUF_VERSION), got $$buf_version"; \
		echo "Use the same version as CI or override: make BUF_VERSION=$$buf_version <target>"; \
		exit 1; \
	fi
