SHELL := /bin/bash
PROJECT=clinic
GOPATH ?= $(shell go env GOPATH)
ROOT := $(shell pwd)
OUTPUT := $(ROOT)/output
OUTPUT_BIN := $(OUTPUT)/bin

# Ensure GOPATH is set before running build process.
ifeq "$(GOPATH)" ""
  $(error Please set the environment variable GOPATH before running `make`)
endif

_COMMIT := $(shell git describe --no-match --always --dirty)
_GITREF := $(shell git rev-parse --abbrev-ref HEAD)
COMMIT  := $(if $(COMMIT),$(COMMIT),$(_COMMIT))
GITREF  := $(if $(GITREF),$(GITREF),$(_GITREF))

REPO    := github.com/pingcap-inc/clinic

LDFLAGS := -w -s
LDFLAGS += -X "$(REPO)/pkg/version.GitHash=$(COMMIT)"
LDFLAGS += -X "$(REPO)/pkg/version.GitRef=$(GITREF)"
LDFLAGS += $(EXTRA_LDFLAGS)

BUILD_FLAG    := -trimpath -buildvcs=false
GOENV         := GO111MODULE=on CGO_ENABLED=1 GOOS=linux GOARCH=amd64
GOENVCGOOFF   := GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64
GO            := $(GOENV) go
GOCGOOFF      := $(GOENVCGOOFF) go
GOBUILD       := $(GO) build $(BUILD_FLAG) -ldflags '$(LDFLAGS)'
GOBUILDCGOOFF := $(GOCGOOFF) build $(BUILD_FLAG) -ldflags '$(LDFLAGS)'
GOTEST        := GO111MODULE=on GODEBUG=cgocheck=0 CGO_ENABLED=1 go test -v
TEST_LDFLAGS  := ""

PACKAGE_LIST := go list ./...| grep -vE "cmd"
PACKAGES     := $$($(PACKAGE_LIST))

.DEFAULT_GOAL := all
.PHONY: all
all: check test build

.PHONY: check
check: mod install-tools generate lint-fix mod

.PHONY: install-tools
install-tools: install-lint install-swagger

.PHONY: install-swagger
install-swagger:
	GOBIN=$(OUTPUT_BIN) go install github.com/swaggo/swag/cmd/swag@v1.16.2

.PHONY: install-lint
install-lint:
	GOBIN=$(OUTPUT_BIN) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8

.PHONY: install-goqueryset
install-goqueryset:
	GOBIN=$(OUTPUT_BIN) go install github.com/tidbcloud/go-queryset/cmd/goqueryset@v0.0.0-20250729021425-422c6cef7691


# Lint and test commands
.PHONY: test
test:
	$(GOTEST) -parallel 1 -p 1 -covermode=atomic -coverprofile=coverage.out -coverpkg=./... ./... 2>&1 | tee test_out.log
	go tool cover -html=coverage.out -o coverage.html

.PHONY: lint
lint: LINTER ?= $(OUTPUT_BIN)/golangci-lint
lint: install-lint
	$(LINTER) run --timeout 10m0s ./...

.PHONY: lint-fix
lint-fix: LINTER ?= $(OUTPUT_BIN)/golangci-lint
lint-fix: install-lint
	$(LINTER) run --timeout 10m0s --fix ./...


# Go mod commands
.PHONY: mod
mod:
	GOPRIVATE=github.com/tidbcloud,github.com/pingcap/dbaas $(GO) mod tidy

.PHONY: check-mod
check-mod: mod
	git diff --exit-code -- go.mod go.sum


# Code generate commands
.PHONY: generate
generate: format-swagger

.PHONY: genearte-goqueryset
genearte-goqueryset: install-goqueryset
	cd pkg/db && GOBIN=$(OUTPUT_BIN) go generate ./...

.PHONY: check-goqueryset
check-goqueryset: genearte-goqueryset
	git diff --exit-code -- pkg/db

.PHONY: generate-swagger
generate-swagger: generate-clinic-swagger generate-ngm-swagger generate-clinic-data-service-swagger

.PHONY: generate-clinic-swagger
generate-clinic-swagger: SWAGGER ?= $(OUTPUT_BIN)/swag
generate-clinic-swagger: install-swagger
	$(SWAGGER) init --parseDependency --instanceName=default_server_api -dir=cmd/server/,pkg/api/ -output=./docs

.PHONY: generate-ngm-swagger
generate-ngm-swagger: SWAGGER ?= $(OUTPUT_BIN)/swag
generate-ngm-swagger: install-swagger
	$(SWAGGER) init --instanceName=ngm_api -dir=cmd/ngm_api/,pkg/ngm/ -output=./docs/ngm_api

.PHONY: generate-clinic-data-service-swagger
generate-clinic-data-service-swagger: SWAGGER ?= $(OUTPUT_BIN)/swag
generate-clinic-data-service-swagger: install-swagger
	$(SWAGGER) init -g cmd/api/main.go -d clinic_data_service -o ./clinic_data_service/docs

.PHONY: check-swagger
check-swagger: format-swagger
	git diff --exit-code -- docs/ clinic_data_service/docs/

.PHONY: format-swagger
format-swagger: SWAGGER ?= $(OUTPUT_BIN)/swag
format-swagger: generate-swagger
	$(SWAGGER) fmt -g=main.go -d=cmd/server/,pkg/api/
	$(SWAGGER) fmt -g=main.go -d=cmd/ngm_api/,pkg/ngm/


# Build commands
.PHONY: build
build: build-clinic-server build-clinic-recovery build-internal-server build-task-manager build-importer build-uploader build-cleanup-user ngm_api

.PHONY: clean
clean:
	rm -rf bin
	rm -f '"$(shell go env GOCACHE)/../golangci-lint"'
	go clean -i -cache -testcache -fuzzcache -x

.PHONY: build-clinic-server
build-clinic-server: OUTPUT_DIR ?= ./bin
build-clinic-server:
	$(GOBUILD) -o $(OUTPUT_DIR)/server ./cmd/server/main.go

.PHONY: build-clinic-recovery
build-clinic-recovery: OUTPUT_DIR ?= ./bin
build-clinic-recovery:
	$(GOBUILD) -o $(OUTPUT_DIR)/cluster_recovery ./cmd/cluster_recovery/main.go

.PHONY: build-internal-server
build-internal-server: OUTPUT_DIR ?= ./bin
build-internal-server:
	$(GOBUILD) -o $(OUTPUT_DIR)/internal_server ./cmd/internal_server/main.go

.PHONY: build-task-manager
build-task-manager: OUTPUT_DIR ?= ./bin
build-task-manager:
	$(GOBUILD) -o $(OUTPUT_DIR)/task_manager ./cmd/task_manager/main.go

.PHONY: build-importer
build-importer: OUTPUT_DIR ?= ./bin
build-importer:
	$(GOBUILD) -o $(OUTPUT_DIR)/importer ./cmd/importer/main.go

.PHONY: build-uploader
build-uploader: OUTPUT_DIR ?= ./bin
build-uploader:
	$(GOBUILD) -o $(OUTPUT_DIR)/uploader ./cmd/uploader/main.go

.PHONY: build-cleanup-user
build-cleanup-user: OUTPUT_DIR ?= ./bin
build-cleanup-user:
	$(GOBUILDCGOOFF) -o $(OUTPUT_DIR)/cleanup_user ./tools/cleanup_user/main.go

.PHONY: build_ngm_api
build_ngm_api: OUTPUT_DIR ?= ./bin
build_ngm_api:
	$(GOBUILD) -o $(OUTPUT_DIR)/ngm_api ./cmd/ngm_api/main.go

.PHONY: build-api-gateway
build-api-gateway:
	$(GOBUILDCGOOFF) -o bin/clinic_auth cmd/api_gateway/clinic/main.go
	$(GOBUILDCGOOFF) -o bin/dbaas_auth ./cmd/api_gateway/tidbcloud

.PHONY: build-clinic-data-service
build-clinic-data-service: OUTPUT_DIR ?= ./bin
build-clinic-data-service:
	cd clinic_data_service && $(GOBUILDCGOOFF) -o $(OUTPUT_DIR)/clinic-data-service ./cmd/api/main.go

# Docker commands
.PHONY: docker_push
docker_push:
	docker push ${IMG}

.PHONY: docker_build_server
docker_build_server: build-clinic-server build-clinic-recovery
	docker build -f deploy/clinic/Dockerfile -t ${IMG} .

.PHONY: docker_build_task_manager
docker_build_task_manager: build-task-manager
	docker build -f deploy/task_manager/Dockerfile -t ${IMG} .

.PHONY: docker_build_internal_api
docker_build_internal_api: build-internal-server
	docker build -f deploy/internal_server/Dockerfile -t ${IMG} .

.PHONY: docker_build_importer
docker_build_importer: build-importer
	docker build -f deploy/importer/Dockerfile -t ${IMG} .

.PHONY: docker_build_uploader
docker_build_uploader: build-uploader
	docker build -f deploy/uploader/Dockerfile -t ${IMG} .

.PHONY: docker_api_gateway
docker_api_gateway: build-api-gateway
	docker build -f deploy/api_gateway/Dockerfile -t ${IMG} .

.PHONY: docker_build_cleanup_user
docker_build_cleanup_user:
	docker buildx build --platform linux/amd64 --build-arg GITHUB_TOKEN=${token} -f deploy/cleanup_user/Dockerfile -t ${IMG} .

.PHONY: docker_build_ngm_api
docker_build_ngm_api: build_ngm_api
	docker build -f deploy/ngm_api/Dockerfile -t ${IMG} .

.PHONY: docker_build_clinic_data_service
docker_build_clinic_data_service: build-clinic-data-service
	docker build -f deploy/clinic_data_service/Dockerfile -t ${IMG} .
