.PHONY: all build test test-unit test-integration lint coverage clean install help docker-up docker-down docker-test docker-test-integration start stop release release-version godoc

# Binary name
BINARY_NAME=relspec

# Build directory
BUILD_DIR=build

# Go parameters
GOCMD=go
GOBUILD=$(GOCMD) build
GOTEST=$(GOCMD) test
GOGET=$(GOCMD) get
GOMOD=$(GOCMD) mod
GOCLEAN=$(GOCMD) clean

# Version information
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
BUILD_DATE := $(shell date -u +"%Y-%m-%d %H:%M:%S UTC")
LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.buildDate=$(BUILD_DATE)'

# Auto-detect container runtime (Docker or Podman)
CONTAINER_RUNTIME := $(shell \
	if command -v podman > /dev/null 2>&1; then \
		echo "podman"; \
	elif command -v docker > /dev/null 2>&1; then \
		echo "docker"; \
	else \
		echo "none"; \
	fi)

# Detect compose command
COMPOSE_CMD := $(shell \
	if [ "$(CONTAINER_RUNTIME)" = "podman" ]; then \
		echo "podman-compose"; \
	elif command -v docker-compose > /dev/null 2>&1; then \
		echo "docker-compose"; \
	else \
		echo "docker compose"; \
	fi)

all: lint test build ## Run linting, tests, and build

build: deps ## Build the binary
	@echo "Building $(BINARY_NAME) $(VERSION)..."
	@mkdir -p $(BUILD_DIR)
	$(GOBUILD) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME) ./cmd/relspec
	@echo "Build complete: $(BUILD_DIR)/$(BINARY_NAME)"

test: test-unit ## Run all unit tests (alias for test-unit)

test-unit: ## Run unit tests (excludes integration tests)
	@echo "Running unit tests..."
	$(GOTEST) -v -race -coverprofile=coverage.out -covermode=atomic $$(go list ./... | grep -v '/tests/integration' | grep -v '/tests/assets' | grep -v '/pkg/readers/pgsql')

test-integration: ## Run integration tests (requires RELSPEC_TEST_PG_CONN environment variable)
	@echo "Running integration tests..."
	@if [ -z "$$RELSPEC_TEST_PG_CONN" ]; then \
		echo "Error: RELSPEC_TEST_PG_CONN environment variable is not set"; \
		echo "Example: export RELSPEC_TEST_PG_CONN='postgres://relspec:relspec_test_password@localhost:5439/relspec_test'"; \
		exit 1; \
	fi
	@echo "Running PostgreSQL reader tests..."
	$(GOTEST) -v -count=1 ./pkg/readers/pgsql/
	@echo "Running general integration tests..."
	$(GOTEST) -v -count=1 ./tests/integration/

coverage: test ## Run tests with coverage report
	@echo "Generating coverage report..."
	$(GOCMD) tool cover -html=coverage.out -o coverage.html
	@echo "Coverage report generated: coverage.html"

lint: ## Run linter
	@echo "Running linter..."
	@if command -v golangci-lint > /dev/null; then \
		golangci-lint run --config=.golangci.json; \
	else \
		echo "golangci-lint not installed. Install with: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest"; \
		exit 1; \
	fi

lintfix: ## Run linter
	@echo "Running linter..."
	@if command -v golangci-lint > /dev/null; then \
		golangci-lint run --config=.golangci.json --fix; \
	else \
		echo "golangci-lint not installed. Install with: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest"; \
		exit 1; \
	fi

clean: ## Clean build artifacts
	@echo "Cleaning..."
	$(GOCLEAN)
	rm -rf $(BUILD_DIR)
	rm -f coverage.out coverage.html
	@echo "Clean complete"

install: ## Install the binary to $GOPATH/bin
	@echo "Installing $(BINARY_NAME) $(VERSION)..."
	$(GOCMD) install -ldflags "$(LDFLAGS)" ./cmd/relspec
	@echo "Install complete"

deps: ## Download dependencies
	@echo "Downloading dependencies..."
	$(GOMOD) download
	$(GOMOD) tidy
	@echo "Dependencies updated"

godoc: ## Start godoc server on http://localhost:6060
	@echo "Starting godoc server..."
	@GOBIN=$$(go env GOPATH)/bin; \
	if command -v godoc > /dev/null 2>&1; then \
		echo "godoc server running on http://localhost:6060"; \
		echo "View documentation at: http://localhost:6060/pkg/git.warky.dev/wdevs/relspecgo/"; \
		echo "Press Ctrl+C to stop"; \
		godoc -http=:6060; \
	elif [ -f "$$GOBIN/godoc" ]; then \
		echo "godoc server running on http://localhost:6060"; \
		echo "View documentation at: http://localhost:6060/pkg/git.warky.dev/wdevs/relspecgo/"; \
		echo "Press Ctrl+C to stop"; \
		$$GOBIN/godoc -http=:6060; \
	else \
		echo "godoc not installed. Installing..."; \
		go install golang.org/x/tools/cmd/godoc@latest; \
		echo "godoc installed. Starting server..."; \
		echo "godoc server running on http://localhost:6060"; \
		echo "View documentation at: http://localhost:6060/pkg/git.warky.dev/wdevs/relspecgo/"; \
		echo "Press Ctrl+C to stop"; \
		$$GOBIN/godoc -http=:6060; \
	fi

start: docker-up ## Alias for docker-up (start PostgreSQL test database)

stop: docker-down ## Alias for docker-down (stop PostgreSQL test database)

docker-up: ## Start PostgreSQL test database
	@echo "Starting PostgreSQL test database (using $(CONTAINER_RUNTIME))..."
	@if [ "$(CONTAINER_RUNTIME)" = "none" ]; then \
		echo "Error: Neither Docker nor Podman is installed"; \
		exit 1; \
	fi
	@if [ "$(CONTAINER_RUNTIME)" = "podman" ]; then \
		podman run -d --name relspec-test-postgres \
			-e POSTGRES_USER=relspec \
			-e POSTGRES_PASSWORD=relspec_test_password \
			-e POSTGRES_DB=relspec_test \
			-p 5439:5432 \
			-v ./tests/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql:Z \
			postgres:16-alpine 2>/dev/null || echo "Container already running"; \
	else \
		$(COMPOSE_CMD) up -d postgres; \
	fi
	@echo "Waiting for PostgreSQL to be ready..."
	@sleep 3
	@echo "PostgreSQL is running on port 5439"
	@echo "Connection: postgres://relspec:relspec_test_password@localhost:5439/relspec_test"

docker-down: ## Stop PostgreSQL test database
	@echo "Stopping PostgreSQL test database (using $(CONTAINER_RUNTIME))..."
	@if [ "$(CONTAINER_RUNTIME)" = "podman" ]; then \
		podman stop relspec-test-postgres 2>/dev/null || true; \
		podman rm relspec-test-postgres 2>/dev/null || true; \
	else \
		$(COMPOSE_CMD) down; \
	fi
	@echo "PostgreSQL stopped"

docker-test: ## Run PostgreSQL integration tests with Docker/Podman
	@if [ "$(CONTAINER_RUNTIME)" = "podman" ]; then \
		./tests/postgres/run_tests_podman.sh; \
	else \
		./tests/postgres/run_tests.sh; \
	fi

docker-test-integration: docker-up ## Start DB and run integration tests
	@echo "Running integration tests..."
	@sleep 2
	@RELSPEC_TEST_PG_CONN="postgres://relspec:relspec_test_password@localhost:5439/relspec_test" \
		$(GOTEST) -v ./pkg/readers/pgsql/ -count=1 || (make docker-down && exit 1)
	@make docker-down

release: ## Create and push a new release tag (auto-increments patch version)
	@echo "Creating new release..."
	@latest_tag=$$(git describe --tags --abbrev=0 2>/dev/null || echo ""); \
	if [ -z "$$latest_tag" ]; then \
		version="v1.0.0"; \
		echo "No existing tags found. Creating first release: $$version"; \
		commit_logs=$$(git log --pretty=format:"- %s" --no-merges); \
	else \
		echo "Latest tag: $$latest_tag"; \
		version_number=$${latest_tag#v}; \
		IFS='.' read -r major minor patch <<< "$$version_number"; \
		patch=$$((patch + 1)); \
		version="v$$major.$$minor.$$patch"; \
		echo "Creating new release: $$version"; \
		commit_logs=$$(git log "$${latest_tag}..HEAD" --pretty=format:"- %s" --no-merges); \
	fi; \
	if [ -z "$$commit_logs" ]; then \
		tag_message="Release $$version"; \
	else \
		tag_message="Release $$version\n\n$$commit_logs"; \
	fi; \
	git tag -a "$$version" -m "$$tag_message"; \
	git push origin "$$version"; \
	echo "Tag $$version created and pushed to remote repository."

release-version: ## Auto-increment patch version, update package files, commit, tag, and push
	@CURRENT=$$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0"); \
	MAJOR=$$(echo $$CURRENT | sed 's/v\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'); \
	MINOR=$$(echo $$CURRENT | sed 's/v\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'); \
	PATCH=$$(echo $$CURRENT | sed 's/v\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'); \
	NEXT="v$$MAJOR.$$MINOR.$$((PATCH + 1))"; \
	PKGVER="$$MAJOR.$$MINOR.$$((PATCH + 1))"; \
	echo "Current: $$CURRENT → Next: $$NEXT"; \
	sed -i "s/^pkgver=.*/pkgver=$$PKGVER/" linux/arch/PKGBUILD; \
	sed -i "s/^Version:.*/Version:        $$PKGVER/" linux/centos/relspec.spec; \
	git add linux/arch/PKGBUILD linux/centos/relspec.spec; \
	git commit -m "chore(release): update package version to $$PKGVER"; \
	git tag -a "$$NEXT" -m "Release $$NEXT"; \
	git push origin HEAD "$$NEXT"; \
	echo "Pushed $$NEXT — release workflow triggered"

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