.PHONY: \
	docker-build build clean \
	generate generate_mock generate_buf \
	verify test check check-golang check-idl check-pulumi

BIN     = bin
GOBIN   = $(abspath $(BIN))
GOENVS  = GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64
GOFLAGS = -ldflags "-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn -s -w " -v

MOCK_FILES = \
		central/jobqueue/mock_jobqueue/mock.go \
		pkg/ratecontroller/mock_ratecontroller/mock.go \
		internel/dao/user/mock_gen_user.go \
		internel/dao/org/mock_gen_org.go \
		internel/dao/project/mock_gen_project.go \
		internel/dao/security/mock_gen_security.go \
		internel/dao/role/mock_gen_role.go \
		internel/dao/rbac/mock_gen_rbac.go \
		internel/dao/message/mock_gen_message.go \
		internel/dao/cross/mock_gen_cross.go \
		internel/dao/dbuser/mock_gen_dbuser.go \
		internel/svc/user/mock_gen_user.go \
		internel/svc/project/mock_gen_project.go \
		internel/svc/org/mock_gen_org.go \
		internel/svc/security/mock_gen_security.go \
		internel/svc/message/mock_gen_message.go \
		thirdparty/account/mock_gen_account.go \
		thirdparty/infra/mock_gen_infra.go \
		thirdparty/dataflow/mock_gen_dataflow.go \
		idl/pbgen/proto/account/mock_gen_account.go \


export DOCKER_BUILDKIT := 1
export GOBIN           := $(GOBIN)
export PATH            := ${GOBIN}:$(PATH)
export SHELL           := /bin/bash

docker-build:
	docker build --secret id=github_token,src=.pingcap/github_token --target runtime -f .pingcap/Dockerfile . -t account:$$(git rev-parse --short HEAD)

build: generate
	$(GOENVS) go build $(GOFLAGS) -o admin/bin/server admin/cmd/server/main.go
	$(GOENVS) go build $(GOFLAGS) -o central/bin/acl central/cmd/acl/main.go
	$(GOENVS) go build $(GOFLAGS) -o central/bin/openapi central/cmd/openapi/main.go
	$(GOENVS) go build $(GOFLAGS) -o central/bin/central central/cmd/central/main.go
	$(GOENVS) go build $(GOFLAGS) -o central/bin/worker central/cmd/worker/main.go
	$(GOENVS) go build $(GOFLAGS) -o central/bin/provider central/cmd/provider/main.go

generate: generate_buf generate_mock generate_openapi_buf

regenerate: clean generate

generate_mock: $(MOCK_FILES) generate_buf


generate_buf: $(BIN)/buf
	cd idl/idl && ${GOBIN}/buf generate && cp ../pbgen/proto/central/service.swagger.json ../../central/docs/

generate_openapi_buf: $(BIN)/buf
	cd idl/openapi_idl && ${GOBIN}/buf generate && cp ../pbgen/proto/v1beta1/service.swagger.json ../../central/docs/gwopenapi/

generate_admin_docs: $(BIN)/swag
	cd admin && swag init --parseDependency --parseInternal -d api,forms -g api.go --output docs/

generate_openapi_docs: $(BIN)/swag
	 cd central/api && swag  init --parseDependency --parseInternal -d ./  -g openapi_sqluser.go  --tags Account  --output central/docs/openapi



verify: check test

test: $(BIN)/gotestsum generate
	@mkdir -p coverage
	@(env AWS_WEB_IDENTITY_TOKEN_FILE=fake GCP_WORKLOAD_IDENTITY_AUDIENCE=fake GCP_IMPERSONATE_SA=fake \
		./hack/start-db-server.sh \
		${GOBIN}/gotestsum --debug --junitfile unit-tests.xml -- -cover -coverprofile=coverage/coverage.out -race -p=1 ./...)

test_onion: $(BIN)/gotestsum generate
	@mkdir -p coverage
	@(env AWS_WEB_IDENTITY_TOKEN_FILE=fake GCP_WORKLOAD_IDENTITY_AUDIENCE=fake GCP_IMPERSONATE_SA=fake \
		./hack/start-db-server.sh \
		${GOBIN}/gotestsum --debug --junitfile unit-tests.xml -- -cover -coverprofile=coverage/coverage.out -race -p=1 ./controllers/... ./internel/dao/... ./internel/svc/... ./thirdparty/... ./utils/...)

check: check-golang check-buf check-pulumi

check-golang: $(BIN)/golangci-lint generate
	@echo "Verifying golangci-lint binary is built with expected Go version..."
	@strings $(BIN)/golangci-lint | grep go1.
	${GOBIN}/golangci-lint cache clean
	${GOBIN}/golangci-lint run -v --config .golangci.yml

check-buf: generate_buf
	cd idl/idl && buf lint

check-pulumi:
	./hack/check_pulumi.sh

central/jobqueue/mock_jobqueue/mock.go: central/jobqueue/jobqueue.go $(BIN)/mockgen
	${GOBIN}/mockgen -source=./central/jobqueue/jobqueue.go -destination ./central/jobqueue/mock_jobqueue/mock.go -package mock_jobqueue

internel/dao/user/mock_gen_user.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/dao/user/user.go -destination ./internel/dao/user/mock_gen_user.go -package=user

internel/dao/project/mock_gen_project.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/dao/project/project.go -destination ./internel/dao/project/mock_gen_project.go -package=project

internel/dao/org/mock_gen_org.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/dao/org/org.go -destination ./internel/dao/org/mock_gen_org.go -package=org

internel/dao/security/mock_gen_security.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/dao/security/security.go -destination ./internel/dao/security/mock_gen_security.go -package=security

internel/dao/role/mock_gen_role.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/dao/role/role.go -destination ./internel/dao/role/mock_gen_role.go -package=role

internel/dao/rbac/mock_gen_rbac.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/dao/rbac/rbac.go -destination ./internel/dao/rbac/mock_gen_rbac.go -package=rbac

internel/dao/message/mock_gen_message.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/dao/message/message.go -destination ./internel/dao/message/mock_gen_message.go -package=message

internel/dao/cross/mock_gen_cross.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/dao/cross/cross.go -destination ./internel/dao/cross/mock_gen_cross.go -package=cross

internel/dao/dbuser/mock_gen_dbuser.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/dao/dbuser/db_user.go -destination ./internel/dao/dbuser/mock_gen_db_user.go -package=dbuser

internel/svc/user/mock_gen_user.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/svc/user/user_svc.go -destination ./internel/svc/user/mock_gen_user.go -package=user

internel/svc/project/mock_gen_project.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/svc/project/project.go -destination ./internel/svc/project/mock_gen_project.go -package=project

internel/svc/org/mock_gen_org.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/svc/org/org.go -destination ./internel/svc/org/mock_gen_org.go -package=org

internel/svc/security/mock_gen_security.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/svc/security/security.go -destination ./internel/svc/security/mock_gen_security.go -package=security

internel/svc/message/mock_gen_message.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/svc/message/message.go -destination ./internel/svc/message/mock_gen_message.go -package=message

thirdparty/account/mock_gen_account.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./thirdparty/account/account.go -destination ./thirdparty/account/mock_gen_account.go -package=account

internel/svc/dbuser/mock_gen_dbuser.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./internel/svc/dbuser/dbuser.go -destination ./internel/svc/dbuser/mock_gen_dbuser.go -package=dbuser

thirdparty/infra/mock_gen_infra.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./thirdparty/infra/infra.go -destination ./thirdparty/infra/mock_gen_infra.go -package=infra

thirdparty/dataflow/mock_gen_dataflow.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./thirdparty/dataflow/dataflow.go -destination ./thirdparty/dataflow/mock_gen_dataflow.go -package=dataflow

idl/pbgen/proto/account/mock_gen_account.go: $(BIN)/mockgen
	${GOBIN}/mockgen -source=./idl/pbgen/proto/account/account_grpc.pb.go -destination ./idl/pbgen/proto/account/mock_gen_account.go -package=account

pkg/ratecontroller/mock_ratecontroller/mock.go: pkg/ratecontroller/types/types.go $(BIN)/mockgen
	${GOBIN}/mockgen -source=./pkg/ratecontroller/types/types.go -destination ./pkg/ratecontroller/mock_ratecontroller/mock.go -package mock_ratecontroller

internel/dao/entity/autogenerated_entity.go: $(BIN)/goqueryset internel/dao/entity/entity.go
	go generate internel/dao/entity/entity.go

clean:
	go clean
	rm -f $(BIN)/*
	rm -f central/bin/*
	rm -f admin/bin/*
	#rm -f internel/dao/entity/autogenerated_entity.go
	rm -f ${MOCK_FILES}

coverage-after-test: $(BIN)/gcov2lcov
	cat coverage/coverage.out | grep -v 'mock*.go' | grep -v 'idl/pbgen' > coverage/cover.out
	${GOBIN}/gcov2lcov -infile=coverage/cover.out -outfile=coverage/coverage.out.lcov

$(BIN):
	@mkdir -p $@

$(BIN)/%: $(BIN)
	go install $(PACKAGE)

reinstall-golangci-lint:
	@rm -f $(BIN)/golangci-lint
	@GO_VERSION=$$(go version) && echo "Installing golangci-lint with $$GO_VERSION"
	@make $(BIN)/golangci-lint


# bufbuild requires go1.18 since v1.1.1.
$(BIN)/buf: PACKAGE=github.com/bufbuild/buf/cmd/buf@v1.1.0
$(BIN)/buf: ${BIN}/protoc-gen-buf-breaking ${BIN}/protoc-gen-buf-lint ${BIN}/protoc-gen-go ${BIN}/protoc-gen-go-grpc ${BIN}/protoc-gen-grpc-gateway ${BIN}/protoc-gen-openapiv2

$(BIN)/swag: PACKAGE=github.com/swaggo/swag/cmd/swag@latest

$(BIN)/protoc-gen-buf-breaking: PACKAGE=github.com/bufbuild/buf/cmd/protoc-gen-buf-breaking@v1.1.0

$(BIN)/protoc-gen-buf-lint: PACKAGE=github.com/bufbuild/buf/cmd/protoc-gen-buf-lint@v1.1.0

$(BIN)/protoc-gen-go: PACKAGE=google.golang.org/protobuf/cmd/protoc-gen-go@v1.28

$(BIN)/protoc-gen-go-grpc: PACKAGE=google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

$(BIN)/protoc-gen-grpc-gateway: PACKAGE=github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.10.3

$(BIN)/protoc-gen-openapiv2: PACKAGE=github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.10.3

$(BIN)/mockgen: PACKAGE=github.com/golang/mock/mockgen@v1.6.0

$(BIN)/goqueryset: PACKAGE=github.com/tidbcloud/go-queryset/cmd/goqueryset@master

$(BIN)/gotestsum: PACKAGE=gotest.tools/gotestsum@v1.12.2

$(BIN)/golangci-lint: PACKAGE=github.com/golangci/golangci-lint/cmd/golangci-lint@latest

$(BIN)/wire: PACKAGE=github.com/google/wire/cmd/wire@latest

$(BIN)/gcov2lcov: PACKAGE=github.com/jandelgado/gcov2lcov@v1.0.5

gapi-lint:
	cd idl/openapi_idl; \
	set -e ;\
	TMP=$$(mktemp -d) ;\
	buf export . --output $$TMP ;\
	api-linter -I $$TMP "openapi/v1beta1/service.proto" ;\
	rm -rf $$TMP;
