SHELL := /bin/sh

MODULE     := git.morlana.online/f.weber/vault-tui
PKG        := ./cmd/vault-tui
BIN        := vault-tui
DIST       := dist
PREFIX     ?= $(HOME)/.local
GOBIN      ?= $(PREFIX)/bin

VERSION    ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
COMMIT     := $(shell git rev-parse --short HEAD 2>/dev/null || echo none)
DATE       := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
PRERELEASE ?= false
LDFLAGS    := -s -w -X main.version=$(VERSION) -X main.commit=$(COMMIT) -X main.date=$(DATE) -X main.prerelease=$(PRERELEASE)
GOFLAGS    := -trimpath
CGO_ENABLED ?= 0

TAGS       ?=
CLOUD_TAGS := cloud

PLATFORMS  ?= linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64

GOLANGCI   := $(shell command -v golangci-lint 2>/dev/null)

.PHONY: help build build-cloud all run run-cloud install install-cloud uninstall \
        test test-race test-cloud cover cover-html fmt fmt-check vet lint tidy tidy-check \
        check release release-cloud clean version

## help: show this help
help:
	@echo "vault-tui — make targets"
	@echo ""
	@awk 'BEGIN {FS = ":.*## "} /^[a-zA-Z0-9_-]+:.*## / {printf "  \033[36m%-16s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
	@echo ""
	@echo "Variables: TAGS=cloud (adds cloud auth to any target), PREFIX, GOBIN, PLATFORMS, VERSION, PRERELEASE"

## build: build the default binary (no cloud auth) into dist/
build: ## build the default binary (no cloud auth) into dist/
	@mkdir -p $(DIST)
	CGO_ENABLED=$(CGO_ENABLED) go build $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(DIST)/$(BIN) $(PKG)
	@echo "built $(DIST)/$(BIN) ($(VERSION))"

## build-cloud: build with AWS/Azure/GCP auth included
build-cloud: ## build with AWS/Azure/GCP auth included
	@$(MAKE) build TAGS="$(CLOUD_TAGS) $(TAGS)" BIN=$(BIN)-cloud

## all: build both the default and cloud-enabled binaries
all: build build-cloud ## build both the default and cloud-enabled binaries

## run: build and run the default binary (pass args via ARGS="...")
run: build ## build and run the default binary (pass args via ARGS="...")
	@./$(DIST)/$(BIN) $(ARGS)

## run-cloud: build and run the cloud-enabled binary (pass args via ARGS="...")
run-cloud: build-cloud ## build and run the cloud-enabled binary (pass args via ARGS="...")
	@./$(DIST)/$(BIN)-cloud $(ARGS)

## install: go install the default binary into GOBIN/PREFIX
install: ## go install the default binary into GOBIN/PREFIX
	GOBIN=$(GOBIN) CGO_ENABLED=$(CGO_ENABLED) go install $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' $(PKG)
	@echo "installed $(BIN) to $(GOBIN)"

## install-cloud: go install the cloud-enabled binary into GOBIN/PREFIX
install-cloud: ## go install the cloud-enabled binary into GOBIN/PREFIX
	@$(MAKE) install TAGS="$(CLOUD_TAGS) $(TAGS)"

## uninstall: remove the installed binary from GOBIN/PREFIX
uninstall: ## remove the installed binary from GOBIN/PREFIX
	rm -f $(GOBIN)/$(BIN)

## test: run tests (default build tags)
test: ## run tests (default build tags)
	go test $(GOFLAGS) -tags '$(TAGS)' ./...

## test-race: run tests with the race detector
test-race: ## run tests with the race detector
	CGO_ENABLED=1 go test $(GOFLAGS) -tags '$(TAGS)' -race ./...

## test-cloud: run tests with cloud auth compiled in
test-cloud: ## run tests with cloud auth compiled in
	@$(MAKE) test TAGS="$(CLOUD_TAGS) $(TAGS)"

## cover: run tests and write coverage.out
cover: ## run tests and write coverage.out
	go test $(GOFLAGS) -tags '$(TAGS)' -coverprofile=coverage.out ./...
	go tool cover -func=coverage.out | tail -1

## cover-html: open an HTML coverage report from coverage.out
cover-html: cover ## open an HTML coverage report from coverage.out
	go tool cover -html=coverage.out -o coverage.html
	@echo "wrote coverage.html"

## fmt: format all Go source in place
fmt: ## format all Go source in place
	gofmt -l -w .

## fmt-check: fail if any file is not gofmt-formatted
fmt-check: ## fail if any file is not gofmt-formatted
	@unformatted="$$(gofmt -l .)"; \
	if [ -n "$$unformatted" ]; then \
		echo "not gofmt-formatted:"; echo "$$unformatted"; exit 1; \
	fi

## vet: run go vet
vet: ## run go vet
	go vet -tags '$(TAGS)' ./...

## lint: run golangci-lint if installed, else fall back to go vet
lint: ## run golangci-lint if installed, else fall back to go vet
ifdef GOLANGCI
	golangci-lint run ./...
else
	@echo "golangci-lint not found on PATH — running go vet instead"
	@echo "install: https://golangci-lint.run/welcome/install/"
	@$(MAKE) vet
endif

## tidy: run go mod tidy
tidy: ## run go mod tidy
	go mod tidy

## tidy-check: fail if go mod tidy would change go.mod/go.sum
tidy-check: ## fail if go mod tidy would change go.mod/go.sum
	@cp go.mod /tmp/vault-tui-go.mod.orig; cp go.sum /tmp/vault-tui-go.sum.orig
	@go mod tidy
	@diff -q /tmp/vault-tui-go.mod.orig go.mod >/dev/null && diff -q /tmp/vault-tui-go.sum.orig go.sum >/dev/null \
		|| (echo "go.mod/go.sum are not tidy — run 'make tidy' and commit the result" && \
		    cp /tmp/vault-tui-go.mod.orig go.mod && cp /tmp/vault-tui-go.sum.orig go.sum && exit 1)
	@rm -f /tmp/vault-tui-go.mod.orig /tmp/vault-tui-go.sum.orig

## check: fmt-check + vet + lint + test — the pre-commit/CI gate
check: fmt-check vet lint test ## fmt-check + vet + lint + test — the pre-commit/CI gate

## release: cross-compile the default binary for PLATFORMS into dist/, with archives + checksums
release: ## cross-compile the default binary for PLATFORMS into dist/, with archives + checksums
	@$(MAKE) _release TAGS="$(TAGS)" SUFFIX=""

## release-cloud: cross-compile the cloud-enabled binary for PLATFORMS into dist/
release-cloud: ## cross-compile the cloud-enabled binary for PLATFORMS into dist/
	@$(MAKE) _release TAGS="$(CLOUD_TAGS) $(TAGS)" SUFFIX="-cloud"

.PHONY: _release
_release:
	@mkdir -p $(DIST)
	@for plat in $(PLATFORMS); do \
		os=$${plat%/*}; arch=$${plat#*/}; \
		out=$(BIN)$(SUFFIX)-$(VERSION)-$$os-$$arch; \
		ext=""; [ "$$os" = "windows" ] && ext=".exe"; \
		echo "building $$out$$ext"; \
		GOOS=$$os GOARCH=$$arch CGO_ENABLED=0 go build $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(DIST)/$$out$$ext $(PKG) || exit 1; \
		( cd $(DIST) && \
		  if [ "$$os" = "windows" ]; then \
		    zip -q $$out.zip $$out$$ext && rm -f $$out$$ext; \
		  else \
		    tar -czf $$out.tar.gz $$out && rm -f $$out; \
		  fi ); \
	done
	@( cd $(DIST) && sha256sum $(BIN)$(SUFFIX)-$(VERSION)-* > checksums-$(BIN)$(SUFFIX)-$(VERSION).txt 2>/dev/null \
	   || shasum -a 256 $(BIN)$(SUFFIX)-$(VERSION)-* > checksums-$(BIN)$(SUFFIX)-$(VERSION).txt )
	@echo "release artifacts in $(DIST)/"

## clean: remove build artifacts
clean: ## remove build artifacts
	rm -rf $(DIST) coverage.out coverage.html vault-tui vault-tui-cloud

## version: print the version make would embed
version: ## print the version make would embed
	@echo "$(VERSION) (commit $(COMMIT), built $(DATE))"

.DEFAULT_GOAL := help
