BINARY_DIR = ${CURDIR}/build/bin
SO_DIR = ${CURDIR}/build/so
DEDICATED_INSTANCE_METERING_SERVER_BINARY = ${BINARY_DIR}/instance-metering-server
DEDICATED_INSTANCE_METERING_CHECK_BINARY = ${BINARY_DIR}/instance-metering-check
DEDICATED_INSTANCE_METERING_FT_BINARY = ${BINARY_DIR}/instance-metering-ft
DEDICATED_NETWORK_METERING_SERVER_BINARY = ${BINARY_DIR}/network-metering-server
DEDICATED_NETWORK_METERING_CHECK_BINARY = ${BINARY_DIR}/network-metering-check
DEDICATED_METERING_SUPPLEMENTARY_TOOL_BINARY = ${BINARY_DIR}/metering-supplementary-tool
DEDICATED_NEXTGEN_METERING_SERVER_BINARY = ${BINARY_DIR}/nextgen-metering-server
DELTA_RS_GOLANG_LIB = ${SO_DIR}/libdeltalake_golang.so

include Makefile.common

.PHONY: build
build:
	make instance-metering-server
	make network-metering-server
	make network-metering-check
	make instance-metering-check
	@echo "build metering all servers successfully."


instance-metering-server:
	@echo "build dedicated instance metering server start."
	$(GOBUILD) $(RACE_FLAG) -ldflags '$(LDFLAGS) $(CHECK_FLAG)' -o ${DEDICATED_INSTANCE_METERING_SERVER_BINARY} cmd/instancemetering/*.go
	@echo "build dedicated instance metering server successfully."

network-metering-server:
	@echo "build dedicated network metering server start."
	$(GOBUILD) $(RACE_FLAG) -ldflags '$(LDFLAGS) $(CHECK_FLAG)' -o ${DEDICATED_NETWORK_METERING_SERVER_BINARY} cmd/networkmetering/*.go
	@echo "build dedicated network metering server successfully."

network-metering-check:
	@echo "build dedicated network metering check start."
	$(GOBUILD) $(RACE_FLAG) -ldflags '$(LDFLAGS) $(CHECK_FLAG)' -o ${DEDICATED_NETWORK_METERING_CHECK_BINARY} cmd/networkchecktools/*.go
	@echo "build dedicated network metering check successfully."

instance-metering-check:
	@echo "build dedicated instance metering check server start."
	$(GOBUILD) $(RACE_FLAG) -ldflags '$(LDFLAGS) $(CHECK_FLAG)' -o ${DEDICATED_INSTANCE_METERING_CHECK_BINARY} cmd/instancecheck/*.go
	@echo "build dedicated instance metering check server successfully."

instance-metering-ft:
	@echo "build dedicated instance metering ft start."
	$(GOBUILD) $(RACE_FLAG) -ldflags '$(LDFLAGS) $(CHECK_FLAG)' -o ${DEDICATED_INSTANCE_METERING_FT_BINARY} cmd/ftinstance/*.go
	@echo "build dedicated instance metering ft successfully."

metering-supplementary-tool:
	@echo "build metering supplementary tool start."
	$(GOBUILD) $(RACE_FLAG) -ldflags '$(LDFLAGS) $(CHECK_FLAG)' -o ${DEDICATED_METERING_SUPPLEMENTARY_TOOL_BINARY} cmd/supplementary/*.go
	@echo "build metering supplementary tool successfully."

nextgen-metering-server:
	@echo "build NextGen metering server start."
	$(GOBUILD) $(RACE_FLAG) -mod=mod -ldflags '$(LDFLAGS) $(CHECK_FLAG)' -o ${DEDICATED_NEXTGEN_METERING_SERVER_BINARY} cmd/nextgenmetering/*.go
	@echo "build NextGen metering server successfully."

.PHONY: delta-rs-golang
delta-rs-golang: ## Build delta-rs-golang shared library
	@echo "build delta-rs-golang shared library start."
	@mkdir -p ${SO_DIR}
	cd delta-rs-golang && cargo build --release --target x86_64-unknown-linux-gnu
	cp delta-rs-golang/target/x86_64-unknown-linux-gnu/release/libdeltalake_golang.so ${DELTA_RS_GOLANG_LIB}
	@echo "build delta-rs-golang shared library successfully."

.PHONY: nextgen-build
nextgen-build: delta-rs-golang nextgen-metering-server ## Build complete NextGen metering (Rust lib + Go binary)
	@echo "build complete NextGen metering successfully."

.PHONY: nextgen-package
nextgen-package: nextgen-build ## Package NextGen metering for deployment
	@echo "prepare NextGen metering package start."
	@mkdir -p build/package/nextgen
	cp ${DEDICATED_NEXTGEN_METERING_SERVER_BINARY} build/package/nextgen/
	cp ${DELTA_RS_GOLANG_LIB} build/package/nextgen/
	@echo "prepare NextGen metering package successfully."


.PHONY: delta-rs-golang-debug
delta-rs-golang-debug: ## Build delta-rs-golang shared library
	@echo "build delta-rs-golang shared library start."
	@mkdir -p ${SO_DIR}
	cd delta-rs-golang && cargo build --target x86_64-unknown-linux-gnu
	cp delta-rs-golang/target/x86_64-unknown-linux-gnu/debug/libdeltalake_golang.so ${DELTA_RS_GOLANG_LIB}
	@echo "build delta-rs-golang shared library successfully."

.PHONY: nextgen-build-debug
nextgen-build-debug: delta-rs-golang-debug nextgen-metering-server ## Build complete NextGen metering (Rust lib + Go binary)
	@echo "build complete NextGen metering successfully."

.PHONY: nextgen-package-debug
nextgen-package-debug: nextgen-build-debug ## Package NextGen metering for deployment
	@echo "prepare NextGen metering package start."
	@mkdir -p build/package/nextgen
	cp ${DEDICATED_NEXTGEN_METERING_SERVER_BINARY} build/package/nextgen/
	cp ${DELTA_RS_GOLANG_LIB} build/package/nextgen/
	@echo "prepare NextGen metering package successfully."

.PHONY: ut
ut: ## Run unit test against code.
	mkdir -p "$(TEST_DIR)"
	$(GO) install gotest.tools/gotestsum@latest
	@-(gotestsum --junitfile "$(TEST_DIR)/unit-tests.xml" --packages=${PACKAGES})
	-go test -v ${PACKAGES} -coverprofile="$(TEST_DIR)/cover.out"
	go tool cover -html "$(TEST_DIR)/cover.out" -o "$(TEST_DIR)/cover.html"
	@echo "check ut results in $(TEST_DIR)/unit-tests.xml"
	@echo "check ut coverage by opening $(TEST_DIR)/cover.html using browser"

lint: mock
	$(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2
	golangci-lint run --fix -v $$($(LINT_PACKAGES)) --config .golangci.yml
	git diff --exit-code

# don't run it locally, only for CI, use `make gosec` instead
ci_gosec:
	$(GO) install github.com/securego/gosec/v2/cmd/gosec@latest
	gosec -fmt=junit-xml -out=gosec-results.xml -stdout -verbose=text -exclude-dir="agent-control-server/*|data-collector/*|vm-bench/*" -exclude=G103,G104,G204,G304,G307,G401,G404,G501,G505,G601 ./...

gosec:
	mkdir -p "$(TEST_DIR)"
	$(GO) install github.com/securego/gosec/v2/cmd/gosec@latest
	gosec -fmt=junit-xml -out="$(TEST_DIR)/gosec-results.xml" -stdout -verbose=text -exclude-dir="agent-control-server/*|data-collector/*|vm-bench/*" -exclude=G103,G104,G204,G304,G307,G401,G404,G501,G505,G601 ./...
	echo "check gosec result by opening $(TEST_DIR)/gosec-results.xml"

mock:
	@echo "generate mock start."
	$(GO) install go.uber.org/mock/mockgen
	mockgen -destination ./test/mockstorage/mockstorage.go -package mockstorage -source ./pkg/common/utils/storage/storage.go
	mockgen -destination ./test/mockapigateway/mockapigateway.go -package mockapigateway -source ./pkg/common/utils/apigateway/common.go
	mockgen -destination ./test/mocknetworkmetering/mocknetworkmetering.go -package mocknetworkmetering -source ./pkg/networkmetering/*.go
	mockgen -destination ./test/mockrepoter/mockrepoter.go -package mockrepoter -source ./pkg/repoter/interface.go
	mockgen -destination ./test/mockfacade/mockscheduletask.go -package mockfacade -source ./pkg/facade/iface/scheduletask.go
	mockgen -destination ./test/mockfacade/mocktidbclustermeta.go -package mockfacade -source ./pkg/facade/iface/tidbclustermeta.go
	mockgen -destination ./test/mockcheckpoint/mockcheckpoint.go -package mockcheckpoint -source ./pkg/common/checkpoint/checkpoint.go
	mockgen -destination ./test/mockbigquery/mockbigquery.go -package mockbigquery -source ./pkg/common/utils/bigquery/bigquery.go
	mockgen -destination ./test/mocks3storage/mocks3client.go -package mocks3storage -source ./pkg/facade/s3storage/client.go
	mockgen -destination ./test/mocks3storage/mocks3.go -package mocks3storage -source ./pkg/facade/s3storage/s3.go

	@echo "generate mock successfully."

.PHONY: ci_ut
ci_ut: add_ut_file mock ## UT for CI, do not run locally, run `make ut` instead.
	go install github.com/axw/gocov/gocov@latest
	go install github.com/jstemmer/go-junit-report@latest
	go install github.com/AlekSi/gocov-xml@latest
	$(GO) install gotest.tools/gotestsum@latest
	@-(gotestsum --junitfile ./unit-tests.xml --packages=${PACKAGES})
	-go test -v ${PACKAGES} -coverprofile=cover.out
	gocov convert cover.out | gocov-xml > coverage.xml

.PHONY: add_ut_file
add_ut_file: ## Add empty test file to make pkg go file be calculated into ut coverage, mainly for CI, no need to run locally.
	cat build/ci/add_ut_file.sh

