MODULE := code.chimeric.al/chimerical/odidere
CMDS   := $(notdir $(wildcard ./cmd/*))
BINARIES := $(addprefix bin/,$(CMDS))

GO          := go
GOFMT       := go fmt
GOVET       := go vet
GOIMPORTS   := go tool goimports
DEADCODE    := go tool deadcode
GOVULNCHECK := go tool govulncheck
STATICCHECK := go tool staticcheck
BIOME       := biome

BUILDFLAGS := -buildvcs=true
PLATFORMS  := linux/amd64

.PHONY: all build build-all buildinfo check clean deadcode deps fmt help \
        imports install lint run staticcheck test tidy tools uninstall \
	verify vet vulncheck $(CMDS)

## Build all binaries (default target)
all: build

## Display this help screen
help:
	@awk ' \
		/^##/ { doc = substr($$0, 4); next } \
		/^[a-zA-Z0-9_-]+:/ && doc { \
			split($$1, target, ":"); \
			printf "\033[36m%-20s\033[0m %s\n", target[1], doc; \
			doc = "" \
		} \
	' $(MAKEFILE_LIST)

## Build all binaries to bin/
build: $(BINARIES)

## Build binaries for all defined platforms
build-all:
	@for cmd in $(CMDS); do \
		for platform in $(PLATFORMS); do \
			echo "Building $$cmd for $$platform..."; \
			out="bin/$$cmd-$${platform%/*}-$${platform#*/}"; \
			GOOS=$${platform%/*} GOARCH=$${platform#*/} \
			$(GO) build $(BUILDFLAGS) -o $$out ./cmd/$$cmd; \
		done; \
	done

## Build specific binaries (pattern rule)
bin/%: ./cmd/%
	$(GO) build $(BUILDFLAGS) -o $@ ./$<

## Shortcut targets to build specific commands (e.g., 'make admin')
$(CMDS):
	$(GO) build $(BUILDFLAGS) -o bin/$@ ./cmd/$@

## Show version info for built binaries
buildinfo: build
	@for bin in $(BINARIES); do \
		if [ -x $$bin ]; then \
			echo "Info for $$bin:"; \
			$(GO) version -m $$bin || true; \
		fi; \
	done

## Run tests with race detection and coverage
test:
	$(GO) test -cover -race ./...

## Run all linters (fmt, vet, imports, deadcode, vulncheck)
lint: fmt vet imports deadcode vulncheck staticcheck biome

## Format code using go fmt
fmt:
	$(GOFMT) ./...

## Fix imports and format using goimports
imports:
	find . -type f -name '*.go' -not -path './vendor/*' | \
	xargs $(GOIMPORTS) -w -local "$(MODULE)"

## Run go vet
vet:
	$(GOVET) ./...

## Find dead code
deadcode:
	$(DEADCODE) ./...

## Check for vulnerabilities
vulncheck:
	$(GOVULNCHECK) ./...

## Run integration checks (alias for lint)
check: lint

## Tidy go.mod dependencies
tidy:
	$(GO) mod tidy

## Run staticcheck
staticcheck:
	$(STATICCHECK) ./...

## Download dependencies
deps:
	$(GO) mod download

## Verify dependencies
verify:
	$(GO) mod verify

## Install development tools
tools:
	go get -tool golang.org/x/tools/cmd/deadcode@latest
	go get -tool golang.org/x/tools/cmd/goimports@latest
	go get -tool golang.org/x/vuln/cmd/govulncheck@latest
	go get -tool honnef.co/go/tools/cmd/staticcheck@latest

## Run the specified CMD binary (use ARGS="..." to pass arguments)
# trap '' INT prevents colorize-logs from exiting immediately on Ctrl-C,
# allowing it to print remaining output before the application terminates.
run: clean bin/$(CMD)
	./bin/$(CMD) $(ARGS) 2>&1 | (trap '' INT; colorize-logs)

## Clean build artifacts
clean:
	$(GO) clean
	rm -f bin/*

## Install binaries to $GOBIN
install:
	$(GO) install $(BUILDFLAGS) ./cmd/...

## Uninstall binaries from $GOBIN
uninstall:
	@for cmd in $(CMDS); do \
		path=$$( $(GO) env GOBIN )/$$cmd; \
		if [ -z "$$( $(GO) env GOBIN )" ]; \
		then path=$$( $(GO) env GOPATH )/bin/$$cmd; fi; \
		echo "Removing $$path"; \
		rm -f $$path; \
	done

## Lint and format JS/CSS with Biome
biome:
	$(BIOME) check --write internal/service/static/

## Check JS/CSS without writing (for CI)
biome-ci:
	$(BIOME) ci internal/service/static/
