# Makefile for Chirpy.

BINARY_NAME ?= chirpy
BIN_DIR     ?= bin
BINARY      := $(BIN_DIR)/$(BINARY_NAME)

# Prefer tools installed into GOBIN, falling back to PATH.
GOBIN_DIR       := $(shell go env GOPATH)/bin
GOOSE           ?= $(if $(wildcard $(GOBIN_DIR)/goose),$(GOBIN_DIR)/goose,goose)
SQLC            ?= $(if $(wildcard $(GOBIN_DIR)/sqlc),$(GOBIN_DIR)/sqlc,sqlc)
GOLANGCI_LINT   ?= $(if $(wildcard $(GOBIN_DIR)/golangci-lint),$(GOBIN_DIR)/golangci-lint,golangci-lint)

# Load local configuration from .env when present. Note: values in .env must
# not contain a bare '#' character, as Make would treat it as a comment.
DB_URL ?= postgres://postgres:postgres@localhost:5432/chirpy?sslmode=disable
-include .env
export

GO_SOURCES := $(shell find . -name '*.go' -not -path './bin/*' -not -path './internal/database/*')

.DEFAULT_GOAL := help

.PHONY: help build run dev test test-race vet fmt fmt-check tidy lint \
        generate clean migrate-up migrate-down migrate-status migrate-reset \
        install-tools check

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

build: ## Compile the server binary into $(BIN_DIR)
	@mkdir -p $(BIN_DIR)
	go build -o $(BINARY) .

run: build ## Build and run the server
	./$(BINARY)

dev: ## Run the server with the race detector enabled
	go run -race .

test: ## Run all tests
	go test ./...

test-race: ## Run all tests with the race detector
	go test -race ./...

vet: ## Run go vet
	go vet ./...

fmt: ## Format all Go source files
	gofmt -s -w $(GO_SOURCES)

fmt-check: ## Verify Go sources are formatted
	@unformatted="$$(gofmt -l $(GO_SOURCES))"; \
	if [ -n "$$unformatted" ]; then \
		echo "The following files are not formatted:"; \
		echo "$$unformatted"; \
		exit 1; \
	fi

tidy: ## Tidy module dependencies
	go mod tidy

lint: ## Run golangci-lint if installed
	@if ! command -v $(GOLANGCI_LINT) >/dev/null 2>&1; then \
		echo "golangci-lint is not installed. Run 'make install-tools' to install it."; \
		exit 1; \
	fi
	$(GOLANGCI_LINT) run ./...

generate: ## Regenerate the sqlc database query code
	$(SQLC) generate

clean: ## Remove build artifacts
	rm -rf $(BIN_DIR)

migrate-up: ## Apply pending database migrations
	$(GOOSE) -dir sql/schema postgres "$(DB_URL)" up

migrate-down: ## Roll back the most recent migration
	$(GOOSE) -dir sql/schema postgres "$(DB_URL)" down

migrate-status: ## Show the current migration status
	$(GOOSE) -dir sql/schema postgres "$(DB_URL)" status

migrate-reset: ## Roll back all migrations and re-apply them
	$(GOOSE) -dir sql/schema postgres "$(DB_URL)" down-to 0
	$(GOOSE) -dir sql/schema postgres "$(DB_URL)" up

install-tools: ## Install dev tools (goose, sqlc, golangci-lint)
	go install github.com/pressly/goose/v3/cmd/goose@latest
	go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
	go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

check: fmt-check vet test ## Run formatting, vet, and test checks
