# Licensed to Apache Software Foundation (ASF) under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Apache Software Foundation (ASF) licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

mk_path  := $(abspath $(lastword $(MAKEFILE_LIST)))
mk_dir   := $(dir $(mk_path))
tool_bin := $(mk_dir)bin

ifneq (,$(wildcard $(mk_dir).env))
include $(mk_dir).env
export
endif

include scripts/build/version.mk

PROJECTS := ui banyand bydbctl mcp fodc/agent fodc/proxy

TEST_CI_OPTS ?=

##@ Build targets

clean: TARGET=clean
clean: PROJECTS:=api $(PROJECTS) pkg
clean: default  ## Clean artifacts in all projects
	rm -rf build
	rm -f .env
	rm -f *.out

clean-build: TARGET=clean-build
clean-build: default  ## Clean build artifacts in all projects

generate: TARGET=generate
generate: PROJECTS:=api $(PROJECTS) pkg
generate: default  ## Generate API codes

build: TARGET=all
build: default  ## Build all projects

##@ Release targets

release: TARGET=release
release: default  ## Build the release artifacts for all projects, usually the statically linked binaries

##@ Test targets

test: TARGET=test
test: PROJECTS:=$(PROJECTS) pkg test
test: default          ## Run the unit tests in all projects

test-race: TARGET=test-race
test-race: PROJECTS:=$(PROJECTS) pkg test
test-race: default     ## Run the unit tests in all projects with race detector on

test-coverage: TARGET=test-coverage
test-coverage: PROJECTS:=$(PROJECTS) pkg test
test-coverage: default ## Run the unit tests in all projects with coverage analysis on

include scripts/build/ginkgo.mk

test-ci: $(GINKGO) ## Run the unit tests in CI. Usage: make test-ci PKG=./banyand/trace
	$(GINKGO) --race \
	  -ldflags \
	  "-X github.com/apache/skywalking-banyandb/pkg/test/flags.eventuallyTimeout=30s -X github.com/apache/skywalking-banyandb/pkg/test/flags.consistentlyTimeout=10s -X github.com/apache/skywalking-banyandb/pkg/test/flags.LogLevel=error" \
	  $(TEST_CI_OPTS) \
	  $(PKG) 

PKG ?= ./...
GO_VERSION := $(shell grep -E '^go [0-9]+\.[0-9]+' go.mod | awk '{print $$2}')
test-docker: ## Run tests in Docker with constrained resources (2 CPU cores, 4GB RAM). Usage: make test-docker PKG=./banyand/trace
	@echo "Running tests in Docker container (2 CPUs, 4GB RAM) for package: $(PKG)"
	@echo "Using Go version: $(GO_VERSION) (from go.mod)"
	docker run --rm \
	  --cpus=2 \
	  --memory=4g \
	  -v $(mk_dir):/workspace \
	  -w /workspace \
	  golang:$(GO_VERSION) \
	  go run github.com/onsi/ginkgo/v2/ginkgo --race \
	  -ldflags "-X github.com/apache/skywalking-banyandb/pkg/test/flags.eventuallyTimeout=30s -X github.com/apache/skywalking-banyandb/pkg/test/flags.consistentlyTimeout=10s -X github.com/apache/skywalking-banyandb/pkg/test/flags.LogLevel=error" \
	  $(PKG)

##@ Code quality targets

lint: TARGET=lint
lint: PROJECTS:=api $(PROJECTS) pkg scripts/ci/check test
lint: default ## Run the linters on all projects

##@ Vendor update

vendor-update: TARGET=vendor-update
vendor-update: PROJECTS:=$(PROJECTS) pkg test
vendor-update: default ## Run the linters on all projects

##@ Code style targets
tidy:
	go mod tidy

format: TARGET=format
format: PROJECTS:=api $(PROJECTS) pkg scripts/ci/check test
format: tidy
format: default ## Run the linters on all projects

check-req: ## Check the requirements
	@$(MAKE) -C scripts/ci/check test
	@$(MAKE) -C ui check-version
	@$(MAKE) -C mcp check-version

include scripts/build/vuln.mk

vuln-check: $(GOVULNCHECK)
	$(GOVULNCHECK) -show color,verbose ./...	

check: ## Check that the status is consistent with CI
	$(MAKE) license-check
	$(MAKE) format
	$(MAKE) tidy
	git add --renormalize .
	mkdir -p /tmp/artifacts
	git diff >/tmp/artifacts/check.diff 2>&1
	@if [ ! -z "`git status -s`" ]; then \
		echo "Following files are not consistent with CI:"; \
		git status -s; \
		cat /tmp/artifacts/check.diff; \
		exit 1; \
	fi

pre-push: ## Check source files before pushing to the remote repo
	$(MAKE) check-req
	$(MAKE) generate
	$(MAKE) lint
	$(MAKE) check
	$(MAKE) vuln-check

##@ License targets

include scripts/build/license.mk

license-check: $(LICENSE_EYE)
license-check: TARGET=license-check
license-check: PROJECTS:=ui mcp
license-check: default ## Check license header
	$(LICENSE_EYE) header check
 
license-fix: $(LICENSE_EYE)
license-fix: TARGET=license-fix
license-fix: PROJECTS:=ui mcp
license-fix: default ## Fix license header issues
	$(LICENSE_EYE) header fix

license-dep: $(LICENSE_EYE)
license-dep: TARGET=license-dep
license-dep: PROJECTS:=ui mcp
license-dep: default ## Fix license header issues
	@rm -rf $(mk_dir)/dist/licenses
	$(LICENSE_EYE) dep resolve -o $(mk_dir)/dist/licenses -s $(mk_dir)/dist/LICENSE.tpl
	mv $(mk_dir)/ui/ui-licenses $(mk_dir)/dist/licenses
	cat $(mk_dir)/ui/LICENSE >> $(mk_dir)/dist/LICENSE
	mv $(mk_dir)/mcp/mcp-licenses $(mk_dir)/dist/licenses
	cat $(mk_dir)/mcp/LICENSE >> $(mk_dir)/dist/LICENSE

##@ Docker targets

docker.build: TARGET=docker
docker.build: PROJECTS:= banyand bydbctl mcp fodc/agent fodc/proxy
docker.build: default ## Build docker images

docker.push: TARGET=docker.push
docker.push: PROJECTS:= banyand bydbctl mcp fodc/agent fodc/proxy
docker.push: default ## Push docker images

default:
	@for PRJ in $(PROJECTS); do \
		echo "--- $$PRJ: $(TARGET) ---"; \
		$(MAKE) $(TARGET) -C $$PRJ; \
		if [ $$? -ne 0 ]; then \
			exit 1; \
		fi; \
	done

nuke:
	git clean -Xdf

include scripts/build/help.mk

##@ release

RELEASE_SCRIPTS := $(mk_dir)/scripts/release.sh

release-binary: release-source ## Package binary archive
	${RELEASE_SCRIPTS} -b

release-source: ## Package source archive
	${RELEASE_SCRIPTS} -s

release-sign: ## Sign artifacts
	${RELEASE_SCRIPTS} -k banyand
	${RELEASE_SCRIPTS} -k bydbctl
	${RELEASE_SCRIPTS} -k mcp
	${RELEASE_SCRIPTS} -k fodc-agent
	${RELEASE_SCRIPTS} -k fodc-proxy
	${RELEASE_SCRIPTS} -k src

release-assembly: release-binary release-sign ## Generate release package

PUSH_RELEASE_SCRIPTS := $(mk_dir)/scripts/push-release.sh

release-push-candidate: ## Push release candidate
	${PUSH_RELEASE_SCRIPTS}
	
.PHONY: all $(PROJECTS) clean build  default nuke
.PHONY: lint check tidy format pre-push
.PHONY: test test-race test-coverage test-ci test-docker
.PHONY: license-check license-fix license-dep
.PHONY: release release-binary release-source release-sign release-assembly
.PHONY: vendor-update