BIN_DIR := bin
GO_CACHE_DIR := $(CURDIR)/.cache/go-build
SERVER_BIN := $(BIN_DIR)/amcs-server
CMD_SERVER := ./cmd/amcs-server
BUILDINFO_PKG := git.warky.dev/wdevs/amcs/internal/buildinfo
UI_DIR := $(CURDIR)/ui
AMCS_UI_BACKEND ?= http://127.0.0.1:8080
PATCH_INCREMENT ?= 1
RELEASE_VERSION ?=
RELEASE_REMOTE ?= origin
VERSION_TAG ?= $(shell git describe --tags --exact-match 2>/dev/null || echo dev)
COMMIT_SHA ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
BUILD_DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
#RELSPEC ?= $(shell command -v relspec 2>/dev/null || echo $(HOME)/go/bin/relspec)
RELSPEC = /home/hein/dev/relspecgo/build/relspec
SCHEMA_FILES := $(sort $(wildcard schema/*.dbml))
MERGE_TARGET_TMP := $(CURDIR)/.cache/schema.merge-target.dbml
GENERATED_SCHEMA_MIGRATION := migrations/020_generated_schema.sql
GENERATED_MODELS_DIR := internal/generatedmodels
PNPM ?= pnpm
LDFLAGS := -s -w \
	-X $(BUILDINFO_PKG).Version=$(VERSION_TAG) \
	-X $(BUILDINFO_PKG).TagName=$(VERSION_TAG) \
	-X $(BUILDINFO_PKG).Commit=$(COMMIT_SHA) \
	-X $(BUILDINFO_PKG).BuildDate=$(BUILD_DATE)

.PHONY: all build clean migrate release-version release-build test generate-migrations generate-models check-schema-drift build-cli ui-install ui-build ui-dev ui-check help

all: build

help:
	@echo "Available targets:"
	@echo "  build                Build server binary (includes UI build)"
	@echo "  build-cli            Build CLI binary"
	@echo "  test                 Run all tests (includes UI check)"
	@echo "  clean                Remove build artifacts"
	@echo "  migrate              Run database migrations"
	@echo "  release-version      Tag and push a release (auto patch bump or RELEASE_VERSION=vX.Y.Z)"
	@echo "  release-build        Build with a specific release tag (RELEASE_VERSION=vX.Y.Z)"
	@echo "  generate-migrations  Generate SQL migration from DBML schema files"
	@echo "  generate-models      Generate Go models from DBML schema"
	@echo "  check-schema-drift   Verify generated migration matches current schema"
	@echo "  ui-install           Install UI dependencies"
	@echo "  ui-build             Build UI assets"
	@echo "  ui-dev               Start UI dev server with local API proxy"
	@echo "  ui-check             Run UI type checks"

build: ui-build
	@mkdir -p $(BIN_DIR)
	go build -ldflags "$(LDFLAGS)" -o $(SERVER_BIN) $(CMD_SERVER)

ui-install:
	cd $(UI_DIR) && $(PNPM) install --frozen-lockfile

ui-build: ui-install
	cd $(UI_DIR) && $(PNPM) run build

ui-dev: ui-install
	cd $(UI_DIR) && VITE_API_URL=/api AMCS_UI_BACKEND=$(AMCS_UI_BACKEND) $(PNPM) run dev

ui-check: ui-install
	cd $(UI_DIR) && $(PNPM) run check

test: ui-check
	@mkdir -p $(GO_CACHE_DIR)
	GOCACHE=$(GO_CACHE_DIR) go test ./...

release-version:
	@case "$(PATCH_INCREMENT)" in \
		''|*[!0-9]*|0) echo "PATCH_INCREMENT must be a positive integer" >&2; exit 1 ;; \
	esac
	@if ! git diff --quiet || ! git diff --cached --quiet; then \
		echo "Refusing to release from a dirty working tree. Commit or stash changes first." >&2; \
		exit 1; \
	fi
	@next_tag="$(RELEASE_VERSION)"; \
	if [ -z "$$next_tag" ]; then \
		latest=$$(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -n 1); \
		if [ -z "$$latest" ]; then latest="v0.0.0"; fi; \
		version=$${latest#v}; \
		major=$${version%%.*}; \
		rest=$${version#*.}; \
		minor=$${rest%%.*}; \
		patch=$${rest##*.}; \
		next_patch=$$((patch + $(PATCH_INCREMENT))); \
		next_tag="v$$major.$$minor.$$next_patch"; \
	fi; \
	case "$$next_tag" in \
		v[0-9]*.[0-9]*.[0-9]*) ;; \
		*) echo "RELEASE_VERSION must look like vX.Y.Z (got '$$next_tag')" >&2; exit 1 ;; \
	esac; \
	if git rev-parse -q --verify "refs/tags/$$next_tag" >/dev/null; then \
		echo "$$next_tag already exists" >&2; \
		exit 1; \
	fi; \
	git tag -a "$$next_tag" -m "Release $$next_tag"; \
	git push $(RELEASE_REMOTE) "$$next_tag"; \
	$(MAKE) release-build RELEASE_VERSION="$$next_tag"; \
	echo "Released $$next_tag"

release-build:
	@case "$(RELEASE_VERSION)" in \
		v[0-9]*.[0-9]*.[0-9]*) ;; \
		*) echo "RELEASE_VERSION must look like vX.Y.Z" >&2; exit 1 ;; \
	esac
	@$(MAKE) build build-cli VERSION_TAG="$(RELEASE_VERSION)"

migrate:
	./scripts/migrate.sh

clean:
	rm -rf $(BIN_DIR)

generate-migrations:
	@test -n "$(SCHEMA_FILES)" || (echo "No DBML schema files found in schema/" >&2; exit 1)
	@command -v $(RELSPEC) >/dev/null 2>&1 || (echo "relspec not found; install git.warky.dev/wdevs/relspecgo/cmd/relspec@latest" >&2; exit 1)
	@mkdir -p $(dir $(MERGE_TARGET_TMP))
	@: > $(MERGE_TARGET_TMP)
	@schema_list=$$(printf '%s\n' $(SCHEMA_FILES) | paste -sd, -); \
	$(RELSPEC) merge --target dbml --target-path $(MERGE_TARGET_TMP) --source dbml --from-list "$$schema_list" --output pgsql --output-path $(GENERATED_SCHEMA_MIGRATION)

generate-models:
	@test -n "$(SCHEMA_FILES)" || (echo "No DBML schema files found in schema/" >&2; exit 1)
	@./scripts/generate-models.sh

check-schema-drift:
	@test -f $(GENERATED_SCHEMA_MIGRATION) || (echo "$(GENERATED_SCHEMA_MIGRATION) is missing; run make generate-migrations" >&2; exit 1)
	@command -v $(RELSPEC) >/dev/null 2>&1 || (echo "relspec not found; install git.warky.dev/wdevs/relspecgo/cmd/relspec@latest" >&2; exit 1)
	@mkdir -p $(dir $(MERGE_TARGET_TMP))
	@tmpfile=$$(mktemp); \
	: > $(MERGE_TARGET_TMP); \
	schema_list=$$(printf '%s\n' $(SCHEMA_FILES) | paste -sd, -); \
	$(RELSPEC) merge --target dbml --target-path $(MERGE_TARGET_TMP) --source dbml --from-list "$$schema_list" --output pgsql --output-path $$tmpfile; \
	if ! cmp -s $$tmpfile $(GENERATED_SCHEMA_MIGRATION); then \
		echo "Schema drift detected between schema/*.dbml and $(GENERATED_SCHEMA_MIGRATION)" >&2; \
		diff -u $(GENERATED_SCHEMA_MIGRATION) $$tmpfile || true; \
		rm -f $$tmpfile; \
		exit 1; \
	fi; \
	rm -f $$tmpfile

build-cli:
	@mkdir -p $(BIN_DIR)
	go build -o $(BIN_DIR)/amcs-cli ./cmd/amcs-cli
