SHELL=/bin/bash

.PHONY: help
.DEFAULT_GOAL := build
.ONESHELL:

SUFFIX=$(GOOS)_$(GOARCH)
COMMIT_HASH=$(shell git rev-parse HEAD)
GIT_BRANCH=$(shell git branch --show-current | tr '[:upper:]' '[:lower:]')
GIT_VERSION=$(shell git branch --show-current | tr '[:upper:]' '[:lower:]')
BUILD_TIMESTAMP=$(shell date +%s)
export VER?=0.0.0

help: ## Print this help message.
	@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

build-debug:  ## Build for debugging.
	export CGO_ENABLED=1
	export GCLFAGS='-gcflags="all=-N -l"'
	${MAKE} build-base

build: ## Build.
	export CGO_ENABLED=0
	export LDFLAGS_EXT='-extldflags=-static -s -w'
	${MAKE} build-base

build-race: ## Build with -race flag.
	export CGO_ENABLED=1
	export GCLFAGS='-race'
	export LDFLAGS_EXT='-extldflags=-static -s -w'
	${MAKE} build-base

build-base: ## Build binary (select the platform via GOOS / GOARCH env variables).
	go build ${GCLFAGS} -ldflags="${LDFLAGS_EXT} \
					-X 'github.com/kubeshark/kubeshark/misc.GitCommitHash=$(COMMIT_HASH)' \
					-X 'github.com/kubeshark/kubeshark/misc.Branch=$(GIT_BRANCH)' \
					-X 'github.com/kubeshark/kubeshark/misc.BuildTimestamp=$(BUILD_TIMESTAMP)' \
					-X 'github.com/kubeshark/kubeshark/misc.Platform=$(SUFFIX)' \
					-X 'github.com/kubeshark/kubeshark/misc.Ver=$(VER)'" \
					-o bin/kubeshark_$(SUFFIX) kubeshark.go && \
	cd bin && shasum -a 256 kubeshark_${SUFFIX} > kubeshark_${SUFFIX}.sha256

build-brew: ## Build binary for brew/core CI
	go build ${GCLFAGS} -ldflags="${LDFLAGS_EXT} \
					-X 'github.com/kubeshark/kubeshark/misc.GitCommitHash=$(COMMIT_HASH)' \
					-X 'github.com/kubeshark/kubeshark/misc.Branch=$(GIT_BRANCH)' \
					-X 'github.com/kubeshark/kubeshark/misc.BuildTimestamp=$(BUILD_TIMESTAMP)' \
					-X 'github.com/kubeshark/kubeshark/misc.Platform=$(SUFFIX)' \
					-X 'github.com/kubeshark/kubeshark/misc.Ver=$(VER)'" \
					-o kubeshark kubeshark.go

build-windows-amd64:
	$(MAKE) build GOOS=windows GOARCH=amd64 && \
	mv ./bin/kubeshark_windows_amd64 ./bin/kubeshark.exe && \
	rm bin/kubeshark_windows_amd64.sha256 && \
	cd bin && shasum -a 256 kubeshark.exe > kubeshark.exe.sha256

build-all: ## Build for all supported platforms.
	export CGO_ENABLED=0
	echo "Compiling for every OS and Platform" && \
	mkdir -p bin && sed s/_VER_/$(VER)/g RELEASE.md.TEMPLATE >  bin/README.md && \
	$(MAKE) build GOOS=linux GOARCH=amd64 && \
	$(MAKE) build GOOS=linux GOARCH=arm64 && \
	$(MAKE) build GOOS=darwin GOARCH=amd64 && \
	$(MAKE) build GOOS=darwin GOARCH=arm64 && \
	$(MAKE) build-windows-amd64 && \
	echo "---------" && \
	find ./bin -ls

clean: ## Clean all build artifacts.
	go clean
	rm -rf ./bin/*

test: ## Run cli tests.
	@go test ./... -coverpkg=./... -race -coverprofile=coverage.out -covermode=atomic

test-integration: ## Run integration tests (requires Kubernetes cluster).
	@echo "Running integration tests..."
	@LOG_FILE=$$(mktemp /tmp/integration-test.XXXXXX.log); \
	go test -tags=integration -timeout $${INTEGRATION_TIMEOUT:-5m} -v ./integration/... 2>&1 | tee $$LOG_FILE; \
	status=$$?; \
	echo ""; \
	echo "========================================"; \
	echo "         INTEGRATION TEST SUMMARY"; \
	echo "========================================"; \
	grep -E "^(--- PASS|--- FAIL|--- SKIP)" $$LOG_FILE || true; \
	echo "----------------------------------------"; \
	pass=$$(grep -c "^--- PASS" $$LOG_FILE 2>/dev/null || true); \
	fail=$$(grep -c "^--- FAIL" $$LOG_FILE 2>/dev/null || true); \
	skip=$$(grep -c "^--- SKIP" $$LOG_FILE 2>/dev/null || true); \
	echo "PASSED:  $${pass:-0}"; \
	echo "FAILED:  $${fail:-0}"; \
	echo "SKIPPED: $${skip:-0}"; \
	echo "========================================"; \
	rm -f $$LOG_FILE; \
	exit $$status

test-integration-mcp: ## Run only MCP integration tests.
	@echo "Running MCP integration tests..."
	@LOG_FILE=$$(mktemp /tmp/integration-test.XXXXXX.log); \
	go test -tags=integration -timeout $${INTEGRATION_TIMEOUT:-5m} -v ./integration/ -run "MCP" 2>&1 | tee $$LOG_FILE; \
	status=$$?; \
	echo ""; \
	echo "========================================"; \
	echo "         INTEGRATION TEST SUMMARY"; \
	echo "========================================"; \
	grep -E "^(--- PASS|--- FAIL|--- SKIP)" $$LOG_FILE || true; \
	echo "----------------------------------------"; \
	pass=$$(grep -c "^--- PASS" $$LOG_FILE 2>/dev/null || true); \
	fail=$$(grep -c "^--- FAIL" $$LOG_FILE 2>/dev/null || true); \
	skip=$$(grep -c "^--- SKIP" $$LOG_FILE 2>/dev/null || true); \
	echo "PASSED:  $${pass:-0}"; \
	echo "FAILED:  $${fail:-0}"; \
	echo "SKIPPED: $${skip:-0}"; \
	echo "========================================"; \
	rm -f $$LOG_FILE; \
	exit $$status

test-integration-short: ## Run quick integration tests (skips long-running tests).
	@echo "Running quick integration tests..."
	@LOG_FILE=$$(mktemp /tmp/integration-test.XXXXXX.log); \
	go test -tags=integration -timeout $${INTEGRATION_TIMEOUT:-2m} -short -v ./integration/... 2>&1 | tee $$LOG_FILE; \
	status=$$?; \
	echo ""; \
	echo "========================================"; \
	echo "         INTEGRATION TEST SUMMARY"; \
	echo "========================================"; \
	grep -E "^(--- PASS|--- FAIL|--- SKIP)" $$LOG_FILE || true; \
	echo "----------------------------------------"; \
	pass=$$(grep -c "^--- PASS" $$LOG_FILE 2>/dev/null || true); \
	fail=$$(grep -c "^--- FAIL" $$LOG_FILE 2>/dev/null || true); \
	skip=$$(grep -c "^--- SKIP" $$LOG_FILE 2>/dev/null || true); \
	echo "PASSED:  $${pass:-0}"; \
	echo "FAILED:  $${fail:-0}"; \
	echo "SKIPPED: $${skip:-0}"; \
	echo "========================================"; \
	rm -f $$LOG_FILE; \
	exit $$status

helm-test: ## Run Helm lint and unit tests.
	helm lint ./helm-chart
	helm unittest ./helm-chart

helm-test-full: helm-test ## Run Helm tests with kubeconform schema validation.
	helm template kubeshark ./helm-chart | kubeconform -strict -kubernetes-version 1.35.0 -summary
	helm template kubeshark ./helm-chart -f ./helm-chart/tests/fixtures/values-s3.yaml | kubeconform -strict -kubernetes-version 1.35.0 -summary
	helm template kubeshark ./helm-chart -f ./helm-chart/tests/fixtures/values-azblob.yaml | kubeconform -strict -kubernetes-version 1.35.0 -summary
	helm template kubeshark ./helm-chart -f ./helm-chart/tests/fixtures/values-gcs.yaml | kubeconform -strict -kubernetes-version 1.35.0 -summary

lint: ## Lint the source code.
	golangci-lint run

kubectl-view-all-resources: ## This command outputs all Kubernetes resources using YAML format and pipes it to VS Code
	./kubectl.sh view-all-resources

kubectl-view-kubeshark-resources: ## This command outputs all Kubernetes resources in "kubeshark" namespace using YAML format and pipes it to VS Code
	./kubectl.sh view-kubeshark-resources

generate-helm-values: ## Generate the Helm values from config.yaml
# 	[ -f ~/.kubeshark/config.yaml ] && mv ~/.kubeshark/config.yaml ~/.kubeshark/config.yaml.old
	bin/kubeshark__ config>helm-chart/values.yaml
# 	[ -f ~/.kubeshark/config.yaml.old ] && mv ~/.kubeshark/config.yaml.old ~/.kubeshark/config.yaml
# 	sed -i 's/^license:.*/license: ""/' helm-chart/values.yaml && sed -i '1i # find a detailed description here: https://github.com/kubeshark/kubeshark/blob/master/helm-chart/README.md' helm-chart/values.yaml 

generate-manifests: ## Generate the manifests from the Helm chart using default configuration
	helm template kubeshark -n default ./helm-chart > ./manifests/complete.yaml

logs-sniffer:
	export LOGS_POD_PREFIX=kubeshark-worker-
	export LOGS_CONTAINER='-c sniffer'
	export LOGS_FOLLOW=
	${MAKE} logs

logs-sniffer-follow:
	export LOGS_POD_PREFIX=kubeshark-worker-
	export LOGS_CONTAINER='-c sniffer'
	export LOGS_FOLLOW=--follow
	${MAKE} logs

logs-tracer:
	export LOGS_POD_PREFIX=kubeshark-worker-
	export LOGS_CONTAINER='-c tracer'
	export LOGS_FOLLOW=
	${MAKE} logs

logs-tracer-follow:
	export LOGS_POD_PREFIX=kubeshark-worker-
	export LOGS_CONTAINER='-c tracer'
	export LOGS_FOLLOW=--follow
	${MAKE} logs

logs-worker: logs-sniffer

logs-worker-follow: logs-sniffer-follow

logs-hub:
	export LOGS_POD_PREFIX=kubeshark-hub
	export LOGS_FOLLOW=
	${MAKE} logs

logs-hub-follow:
	export LOGS_POD_PREFIX=kubeshark-hub
	export LOGS_FOLLOW=--follow
	${MAKE} logs

logs-front:
	export LOGS_POD_PREFIX=kubeshark-front
	export LOGS_FOLLOW=
	${MAKE} logs

logs-front-follow:
	export LOGS_POD_PREFIX=kubeshark-front
	export LOGS_FOLLOW=--follow
	${MAKE} logs

logs:
	kubectl logs $$(kubectl get pods | awk '$$1 ~ /^$(LOGS_POD_PREFIX)/' | awk 'END {print $$1}') $(LOGS_CONTAINER) $(LOGS_FOLLOW)

ssh-node:
	kubectl ssh node $$(kubectl get nodes | awk 'END {print $$1}')

exec-worker:
	export EXEC_POD_PREFIX=kubeshark-worker-
	${MAKE} exec

exec-hub:
	export EXEC_POD_PREFIX=kubeshark-hub
	${MAKE} exec

exec-front:
	export EXEC_POD_PREFIX=kubeshark-front
	${MAKE} exec

exec:
	kubectl exec --stdin --tty $$(kubectl get pods | awk '$$1 ~ /^$(EXEC_POD_PREFIX)/' | awk 'END {print $$1}') -- /bin/sh

helm-install:
	cd helm-chart && helm install kubeshark . --set tap.docker.tag=$(TAG) && cd ..

helm-install-debug:
	cd helm-chart && helm install kubeshark . --set tap.docker.tag=$(TAG) --set tap.debug=true && cd ..

helm-install-profile:
	cd helm-chart && helm install kubeshark . --set tap.docker.tag=$(TAG) --set tap.pprof.enabled=true && cd ..

helm-uninstall:
	helm uninstall kubeshark

proxy:
	kubeshark proxy

port-forward:
	kubectl port-forward $$(kubectl get pods | awk '$$1 ~ /^$(POD_PREFIX)/' | awk 'END {print $$1}') $(SRC_PORT):$(DST_PORT)

release: ## Print release workflow instructions.
	@echo "Release workflow (2 steps):"
	@echo ""
	@echo "  1. make release-pr VERSION=x.y.z"
	@echo "     Tags sibling repos, bumps version, creates PRs"
	@echo "     (kubeshark + kubeshark.github.io helm chart)."
	@echo "     Review and merge both PRs manually."
	@echo ""
	@echo "  2. (automatic) Tag is created when release PR merges."
	@echo "     Fallback: make release-tag VERSION=x.y.z"

release-pr: ## Step 1: Tag sibling repos, bump version, create release PR.
	@cd ../worker && git checkout master && git pull && git tag -d v$(VERSION); git tag v$(VERSION) && git push origin --tags
	@cd ../hub && git checkout master && git pull && git tag -d v$(VERSION); git tag v$(VERSION) && git push origin --tags
	@cd ../front && git checkout master && git pull && git tag -d v$(VERSION); git tag v$(VERSION) && git push origin --tags
	@cd ../kubeshark && git checkout master && git pull
	@sed -i '' "s/^version:.*/version: \"$(shell echo $(VERSION) | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+)\..*/\1/')\"/" helm-chart/Chart.yaml
	@$(MAKE) build VER=$(VERSION)
	@if [ "$(shell uname)" = "Darwin" ]; then \
		codesign --sign - --force --preserve-metadata=entitlements,requirements,flags,runtime ./bin/kubeshark__; \
	fi
	@$(MAKE) generate-helm-values && $(MAKE) generate-manifests
	@git checkout -b release/v$(VERSION)
	@git add -A .
	@git commit -m ":bookmark: Bump the Helm chart version to $(VERSION)"
	@git push -u origin release/v$(VERSION)
	@gh pr create --title ":bookmark: Release v$(VERSION)" \
		--body "Automated release PR for v$(VERSION)." \
		--base master \
		--reviewer corest
	@git checkout master && git pull
	@cd ../kubeshark.github.io \
		&& git checkout master && git pull \
		&& rm -rf charts/chart \
		&& mkdir charts/chart \
		&& cp -r ../kubeshark/helm-chart/ charts/chart/ \
		&& git checkout -b helm-v$(VERSION) \
		&& git add -A . \
		&& git commit -m ":sparkles: Update the Helm chart to v$(VERSION)" \
		&& git push -u origin helm-v$(VERSION) \
		&& gh pr create --title ":sparkles: Helm chart v$(VERSION)" \
			--body "Update Helm chart for release v$(VERSION)." \
			--base master \
			--reviewer corest \
		&& git checkout master
	@echo ""
	@echo "Release PRs created:"
	@echo "  - kubeshark: Review and merge the release PR."
	@echo "  - kubeshark.github.io: Review and merge the helm chart PR."
	@echo "Tag will be created automatically, or run: make release-tag VERSION=$(VERSION)"

release-tag: ## Step 2 (fallback): Tag master after release PR is merged.
	@echo "Verifying release PR was merged..."
	@if ! gh pr list --state merged --head release/v$(VERSION) --json number --jq '.[0].number' | grep -q .; then \
		echo "Error: No merged PR found for release/v$(VERSION). Merge the PR first."; \
		exit 1; \
	fi
	@git checkout master && git pull
	@git tag -d v$(VERSION) 2>/dev/null; git tag v$(VERSION) && git push origin --tags
	@echo ""
	@echo "Tagged v$(VERSION) on master. GitHub Actions will build the release."

release-dry-run:
	@cd ../worker && git checkout master && git pull 
	# @cd ../tracer && git checkout master && git pull 
	@cd ../hub && git checkout master && git pull
	@cd ../front && git checkout master && git pull 
	@cd ../kubeshark && sed -i "s/^version:.*/version: \"$(shell echo $(VERSION) | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+)\..*/\1/')\"/" helm-chart/Chart.yaml && make
	# @if [ "$(shell uname)" = "Darwin" ]; then \
	# 	codesign --sign - --force --preserve-metadata=entitlements,requirements,flags,runtime ./bin/kubeshark__; \
	# fi
	@make generate-helm-values && make generate-manifests
	@rm -rf ../kubeshark.github.io/charts/chart && mkdir ../kubeshark.github.io/charts/chart && cp -r helm-chart/ ../kubeshark.github.io/charts/chart/
	@cd ../kubeshark.github.io/
	@cd ../kubeshark

branch:
	@cd ../worker && git checkout master && git pull && git checkout -b $(name); git push --set-upstream origin $(name)
	@cd ../hub && git checkout master && git pull && git checkout -b $(name); git push --set-upstream origin $(name)
	@cd ../front && git checkout master && git pull && git checkout -b $(name); git push --set-upstream origin $(name)

switch-to-branch:
	@cd ../worker && git checkout $(name)
	@cd ../hub && git checkout $(name)
	@cd ../front && git checkout $(name)
