.PHONY: build build-dataflow-amd64 \
	check check-idl check-golang \
	lint lint-golang \
	fmt fmt-golang \
	test unit-test ci-unit-test tidy \
	generate generate-idl generate-entity \
	generate-coverage browse-coverage \
	gapi-lint

GO     := GO111MODULE=on go
GOTEST := CGO_ENABLED=1 $(GO) test -p 3 --race
GOBUILD := CGO_ENABLED=0 $(GO) build
CGOBUILD := CGO_ENABLED=1 $(GO) build
GOCOVER := $(GO) tool cover
LDFLAGS += -X "github.com/tidbcloud/dataflow-service-ng/pkg/version.ReleaseVersion=$(shell git describe --tags --dirty --always)"
LDFLAGS += -X "github.com/tidbcloud/dataflow-service-ng/pkg/version.BuildTS=$(shell date -u '+%Y-%m-%d %H:%M:%S')"
LDFLAGS += -X "github.com/tidbcloud/dataflow-service-ng/pkg/version.GitHash=$(shell git rev-parse HEAD)"
LDFLAGS += -X "github.com/tidbcloud/dataflow-service-ng/pkg/version.GitBranch=$(shell git rev-parse --abbrev-ref HEAD)"
TEST_ARTIFACTS_DIR := /tmp/dataflow-service-ng/test-artifacts
TEST_ARTIFACTS_OUT := $(TEST_ARTIFACTS_DIR)/cov.unit_test.out
TEST_ARTIFACTS_FILE_COVER := $(TEST_ARTIFACTS_DIR)/file_coverage.html
TEST_OPTIONS := -timeout 5m -cover -covermode=atomic -coverprofile="$(TEST_ARTIFACTS_OUT)"
FILES := $$(find . -name '*.go' -type f | grep -vE 'mock|vendor|generate|kv_gen|proto|pb\.go|pb\.gw\.go|test\.go')
GENQS := PATH="../../../tools/bin:$(PATH)" go generate entity.go

FAIL_ON_STDOUT := awk '{ print } END { if (NR > 0) { exit 1  }  }'

UNAME := $(shell uname)
BROWSER_OPEN := "unknown"
ifeq ($(UNAME),Darwin)
    BROWSER_OPEN := open -a Safari
endif
ifeq ($(UNAME),Linux)
    BROWSER_OPEN := xdg-open
endif

CONTAINER_TOOL ?= docker

.PHONY: docker-build
docker-build: build
	$(CONTAINER_TOOL) build -t ${IMG} .

.PHONY: docker-push
docker-push:
	$(CONTAINER_TOOL) push ${IMG}

failpoint-enable: tools/bin/failpoint-ctl
	tools/bin/failpoint-ctl enable

failpoint-disable: tools/bin/failpoint-ctl
	tools/bin/failpoint-ctl disable

build: build-dataflow

build-darwin: build-dataflow-darwin

build-dataflow:
	$(GOBUILD) -ldflags '$(LDFLAGS)' -o dist/dataflow cmd/dataflow/main.go

build-dataflow-personal:
	$(GOBUILD) -gcflags "all=-N -l" -ldflags '$(LDFLAGS)' -o dist/dataflow cmd/dataflow/main.go

build-dataflow-amd64:
	GOARCH=amd64 GOOS=linux $(GOBUILD) -ldflags '$(LDFLAGS)' -o dist/dataflow-amd64 cmd/dataflow/main.go

# there are cgo codes in go files of darwin
build-dataflow-darwin:
	$(CGOBUILD) -ldflags '$(LDFLAGS)' -o dist/dataflow cmd/dataflow/main.go

build-dataflow-amd64-personal:
	GOARCH=amd64 GOOS=linux $(GOBUILD) -gcflags "all=-N -l" -ldflags '$(LDFLAGS)' -o dist/dataflow-amd64 cmd/dataflow/main.go

generate: generate-idl generate-entity

generate-idl: tools/bin/buf tools/bin/protoc-gen-validate tools/bin/swagger
	cd idl/idl && PATH='$(shell pwd)/tools/bin:$(PATH)' buf generate -v --path ./agent/ng_agent --template ./template.yaml
	cd idl/idl && PATH='$(shell pwd)/tools/bin:$(PATH)' buf generate -v --path ./agent/ng_agent_common --template ./template.yaml
	mv idl/pbgen/proto/ng_agent/agent.swagger.json api/
	tools/bin/swagger validate api/agent.swagger.json

generate-entity:  app/internal/repo/entity/autogenerated_entity.go

generate4test: tools/bin/mockery
	@(sh ./tools/scripts/gen_mock.sh)

app/internal/repo/entity/autogenerated_entity.go: app/repo/entity/entity.go tools/bin/goqueryset
	cd app/repo/entity && PATH="../../../../tools/bin:$(PATH)" go generate entity.go

check: lint fmt
	@git --no-pager diff --exit-code | $(FAIL_ON_STDOUT)

check-go-in-ci: lint-idl lint-golang fmt-idl fmt-golang
	@git --no-pager diff --exit-code 2>&1 | $(FAIL_ON_STDOUT)

lint: lint-idl lint-golang

lint-golang: tools/bin/golangci-lint
	cd app && ../tools/bin/golangci-lint run

lint-idl: tools/bin/buf
	cd idl/idl && ../../tools/bin/buf lint

fmt: fmt-idl fmt-golang fmt-sh

fmt-golang: tools/bin/golangci-lint tools/bin/gofumpt
	@echo "golangci-lint run --fix"
	cd app && ../tools/bin/golangci-lint run --fix --timeout 10m0s
	@echo "gofmt (simplify)"
	cd app && ../tools/bin/gofumpt -l -w $(FILES) 2>&1 | $(FAIL_ON_STDOUT)

fmt-idl: tools/bin/buf
	tools/bin/buf format -w --exit-code idl/idl/

fmt-sh: tools/bin/shfmt
	tools/bin/shfmt -d -w .

test: unit-test

ci-unit-test: tools/bin/gotestsum tools/bin/failpoint-ctl
	mkdir -p "$(TEST_ARTIFACTS_DIR)"
	make failpoint-enable
	CGO_ENABLED=1 tools/bin/gotestsum --junitfile "$(TEST_ARTIFACTS_DIR)/junit-report.xml" -- \
	-v $(TEST_OPTIONS) ./... \
	|| { make failpoint-disable ; exit 1; }
	make failpoint-disable

unit-test: tools/bin/failpoint-ctl
	mkdir -p "$(TEST_ARTIFACTS_DIR)"
	make failpoint-enable
	$(GOTEST) $(TEST_OPTIONS) ./... \
	|| { make failpoint-disable ; exit 1; }
	make failpoint-disable

APP_DIR_TEST = .test
APP_PACKAGE := ./app/...
APP_COVERAGE_FAIL_UNDER := 70
APP_FILE_ALL_COVERAGE = $(APP_DIR_TEST)/coverage_all.txt
APP_TOTAL_COVERAGE = $(APP_DIR_TEST)/coverage_total.txt
APP_TEST_FLAGS :=  -race -failfast -p=1 -covermode=atomic -timeout 5m

app-unit-test: tools/bin/gotestsum tools/bin/gocovmerge
	mkdir -p $(APP_DIR_TEST)
	@echo running test
	@# skip mock package , bash scripts is too hacky for newbee > <:
	@for package in $$(go list $(APP_PACKAGE)); do \
        if [ `echo $$(echo $$package | tr / -) | grep -E 'mock' | wc -l` -gt 0 ] ; then \
            echo "skip $$package"; \
        elif [ `echo $$(echo $$package | tr / -) | grep -E 'domain' | wc -l` -gt 0 ]; then \
            echo "skip not need test domain $$package"; \
        else \
            coverfile="$(APP_DIR_TEST)/$$(echo $$package | tr / -).cover"; \
            tools/bin/gotestsum -- $(TESAPP_TEST_FLAGST_FLAGS) -coverprofile="$$coverfile" "$$package" -coverpkg="$$package" || exit 1; \
		fi \
	done

app-check-coverage: app-unit-test
	@echo merge all coverage files into one
	@tools/bin/gocovmerge $(APP_DIR_TEST)/*.cover > $(APP_FILE_ALL_COVERAGE)

	#  generate coverage report
	$(GO) tool cover -func $(APP_FILE_ALL_COVERAGE) | tee $(APP_TOTAL_COVERAGE)

	@echo show coverage
	@total_coverage=`tail -1 $(APP_TOTAL_COVERAGE) | cut -d\) -f2 | tr -d '[:space:]|%' | cut -d. -f1` && echo "total coverate is" $$total_coverage

	@echo test coverage
	test `tail -1 $(APP_TOTAL_COVERAGE) | cut -d\) -f2 | tr -d '[:space:]|%' | cut -d. -f1` -ge $(APP_COVERAGE_FAIL_UNDER)

generate-coverage:
	make failpoint-enable
	$(GOCOVER) -html=$(TEST_ARTIFACTS_OUT) -o $(TEST_ARTIFACTS_FILE_COVER)
	make failpoint-disable

browse-coverage: generate-coverage
	$(BROWSER_OPEN) $(TEST_ARTIFACTS_FILE_COVER)

show-total-coverage:
	make failpoint-enable
	$(GOCOVER) -func $(TEST_ARTIFACTS_OUT) | fgrep "total:" | awk '{print $$NF}'
	make failpoint-disable

tidy:
	$(GO) mod tidy -e

# tools
tools/bin/gotestsum: tools/go.mod
	echo "build gotestsum"
	make -C ./tools gotestsum

tools/bin/golangci-lint: tools/go.mod
	echo "build golangci-lint"
	make -C ./tools golangci-lint

tools/bin/goqueryset: tools/go.mod
	echo "build goqueryset"
	make -C ./tools goqueryset

tools/bin/gofumpt: tools/go.mod
	echo "build gofumpt"
	make -C ./tools gofumpt

tools/bin/buf:
	echo "build buf"
	make -C ./tools buf

tools/bin/failpoint-ctl:
	echo "build failpoint-ctl"
	make -C ./tools failpoint-ctl

tools/bin/protoc-gen-validate:
	echo "build protoc-gen-validate"
	make -C ./tools protoc-gen-validate

tools/bin/swagger: tools/go.mod
	echo "build swagger"
	make -C ./tools swagger

tools/bin/gocovmerge: tools/go.mod
	echo "build gocovmerge"
	make -C ./tools gocovmerge

tools/bin/mockery: tools/go.mod
	echo "build mockery"
	make -C ./tools mockery

tools/bin/shfmt: tools/go.mod
	echo "build shfmt"
	make -C ./tools shfmt

import-openapi-test:
	echo -e "run import openapi test: \nmake import-openapi-test API_AK API_SK SERVERLESS_CLUSTER EKS_CLUSTER GKE_CLUSTER \nCLUSTER should be projectId:clusterId"
	./test/import/run.sh --env $(ENV) --api_ak $(API_AK) --api_sk $(API_SK) --serverless_cluster $(SERVERLESS_CLUSTER) --eks_cluster $(EKS_CLUSTER) --gke_cluster $(GKE_CLUSTER)

gapi-lint:
	cd idl/idl/dataflow; \
	set -e ;\
	TMP=$$(mktemp -d) ;\
	buf export . --output $$TMP ;\
	api-linter --config=adminapi/.api-linter.yaml -I $$TMP "adminapi/v1beta1/import.proto" ;\
	api-linter --config=adminapi/.api-linter.yaml -I $$TMP "adminapi/v1beta1/backup.proto" ;\
	api-linter  --config=openapi/.api-linter.yaml -I $$TMP "openapi/v1beta1/changefeed.proto" ;\
	rm -rf $$TMP;

build-dataflow-agent:
	$(GOBUILD) -ldflags '$(LDFLAGS)' -o dist/dataflow-agent cmd/main.go

build-dataflow-agent-amd64:
	GOARCH=amd64 GOOS=linux $(GOBUILD) -ldflags '$(LDFLAGS)' -o dist/dataflow-agent-amd64 cmd/main.go

# there are cgo codes in go files of darwin
build-dataflow-agent-darwin:
	$(CGOBUILD) -ldflags '$(LDFLAGS)' -o dist/dataflow-agent cmd/main.go

