# Lux EVM Makefile

# Root directory
EVM_PATH := $(shell pwd)

# Load constants
GOPATH := $(shell go env GOPATH)
LUX_PLUGIN_DIR ?= $(HOME)/.lux/plugins
# EVM VM ID derived from luxfi/constants.EVMID via cmd/vmid — no base58 hardcoded.
# Lazily expanded so `make help` etc. don't pay the `go run` cost.
EVM_VMID = $(shell go run ./cmd/vmid)

# Git info
EVM_COMMIT := $(shell git rev-parse HEAD 2>/dev/null || echo "unknown")
CURRENT_BRANCH := $(shell git describe --tags --exact-match 2>/dev/null || git symbolic-ref -q --short HEAD || git rev-parse --short HEAD || echo "unknown")

# Lux version from go.mod
LUX_VERSION := $(shell go list -m github.com/luxfi/node 2>/dev/null | awk '{print $$2}')

# EVM version from git
EVM_VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")

# Build flags
LDFLAGS := -X github.com/luxfi/evm/plugin/evm.GitCommit=$(EVM_COMMIT) -X github.com/luxfi/evm/plugin/evm.Version=$(EVM_VERSION)
STATIC_LD_FLAGS :=
CGO_CFLAGS := -O2 -D__BLST_PORTABLE__

# CGO enabled by default for C++/GPU backends, override with CGO_ENABLED=0
CGO_ENABLED ?= 1
export CGO_ENABLED
export CGO_CFLAGS

.PHONY: all build build-node clean test lint install link setup generate help

# Default target
all: build

# Help target
help:
	@echo "Lux EVM Makefile"
	@echo ""
	@echo "Usage:"
	@echo "  make [target]"
	@echo ""
	@echo "Targets:"
	@echo "  all             Build EVM plugin (default)"
	@echo "  build           Build EVM plugin to build/evm"
	@echo "  build-node      Build standalone evm-node binary"
	@echo "  install         Install EVM plugin to ~/.lux/plugins (copy)"
	@echo "  link            Link EVM plugin to ~/.lux/plugins/current (symlink)"
	@echo "  clean           Clean build artifacts"
	@echo "  test            Run all tests"
	@echo "  test-unit       Run unit tests"
	@echo "  test-e2e        Run end-to-end tests"
	@echo "  lint            Run linters"
	@echo "  generate        Generate code (mocks, codecs)"
	@echo "  setup           Setup development environment"
	@echo "  docker          Build Docker image"
	@echo ""

# Build the EVM plugin
build: ensure-deps
	@echo "Building Lux EVM @ $(EVM_VERSION) ($(EVM_COMMIT))"
	@mkdir -p build
	go build -ldflags "$(LDFLAGS) $(STATIC_LD_FLAGS)" -o build/evm ./plugin/*.go
	@echo "Built: build/evm"


# Ensure dependencies are in place
ensure-deps:
	@if [ ! -f go.sum ]; then \
		echo "go.sum missing, running go mod download..."; \
		go mod download; \
	fi

# Fix dependencies
fix-deps:
	@echo "Fixing dependencies..."
	go mod download
	@echo "Dependencies fixed."

# Install to plugin directory (copy binary). VM ID derived from go constants.
install: build
	@vmid="$$(go run ./cmd/vmid)"; \
		mkdir -p $(LUX_PLUGIN_DIR); \
		install -m 0755 build/evm $(LUX_PLUGIN_DIR)/$$vmid; \
		[ "$$(uname -s)" = "Darwin" ] && codesign --force --sign - $(LUX_PLUGIN_DIR)/$$vmid >/dev/null 2>&1 || true; \
		echo "Installed: $(LUX_PLUGIN_DIR)/$$vmid"

# Symlink for development (rebuild → no reinstall step needed)
link: build
	@vmid="$$(go run ./cmd/vmid)"; \
		mkdir -p $(LUX_PLUGIN_DIR); \
		ln -sf $(EVM_PATH)/build/evm $(LUX_PLUGIN_DIR)/$$vmid; \
		echo "Linked: $(LUX_PLUGIN_DIR)/$$vmid -> $(EVM_PATH)/build/evm"

# Clean build artifacts
clean:
	@echo "Cleaning build artifacts..."
	@rm -rf build/
	@rm -rf bin/
	@vmid="$$(go run ./cmd/vmid 2>/dev/null)" && rm -f $(LUX_PLUGIN_DIR)/$$vmid || true

# Run all tests
test:
	@echo "Running all tests..."
	./scripts/build_test.sh

# Run unit tests only
test-unit:
	@echo "Running unit tests..."
	go test -v -timeout=30m ./...

# Run unit tests with race detection
test-race:
	@echo "Running tests with race detection..."
	go test -v -race -timeout=30m ./...

# Run E2E tests
test-e2e: test-e2e-precompile test-e2e-load test-e2e-warp

test-e2e-precompile:
	@echo "Running E2E precompile tests..."
	./scripts/run_ginkgo_precompile.sh

test-e2e-load:
	@echo "Running E2E load tests..."
	./scripts/run_ginkgo_load.sh

test-e2e-warp:
	@echo "Running E2E warp tests..."
	./scripts/run_ginkgo_warp.sh

# Benchmarks
bench:
	@echo "Running benchmarks..."
	./scripts/build_bench_precompiles.sh

# Coverage
coverage:
	@echo "Generating coverage report..."
	go test -v -coverprofile=coverage.out ./...
	./scripts/coverage.sh

# Linting
lint:
	@echo "Running linters..."
	./scripts/lint.sh

lint-all:
	@echo "Running all lint checks..."
	@$(MAKE) lint
	@./scripts/actionlint.sh
	@./scripts/shellcheck.sh
	@$(MAKE) check-generate

# Code generation
generate: generate-mocks generate-codec

generate-mocks:
	@echo "Generating mocks..."
	@grep -lr -E '^// Code generated by MockGen\. DO NOT EDIT\.' . | xargs -r rm
	@go generate -run "go.uber.org/mock/mockgen" ./...

generate-codec:
	@echo "Generating codec..."
	@grep -lr -E '^// Code generated by github\.com\/fjl\/gencodec\. DO NOT EDIT\.' . | xargs -r rm
	@go generate -run "github.com/fjl/gencodec" ./...

# Check if generated files are up to date
check-generate: generate
	@echo "Checking if generated files are up to date..."
	@git diff --exit-code || (echo "Generated files are out of date. Please run 'make generate'." && exit 1)

# Setup development environment
setup:
	@echo "Setting up development environment..."
	@echo "Installing dependencies..."
	go mod download
	@echo "Installing tools..."
	go install -v github.com/fjl/gencodec@latest
	go install -v go.uber.org/mock/mockgen@latest
	@echo "Setting up contracts..."
	cd contracts && npm ci && npx hardhat clean && npx hardhat compile

# Docker image
docker:
	@echo "Building Docker image..."
	./scripts/build_docker_image.sh

docker-test:
	@echo "Testing Docker image build..."
	./scripts/tests.build_docker_image.sh

# Version management
check-version:
	@echo "Checking luxd version..."
	@echo "Current luxd version: $(LUX_VERSION)"
	./scripts/update_luxd_version.sh

# Install luxd for testing
install-luxd:
	@echo "Installing luxd..."
	./scripts/install_luxd_release.sh

# Development helpers
dev-shell:
	@echo "Starting development shell..."
	./scripts/dev_shell.sh

# Run local node for testing
run-local: build
	@echo "Running local node..."
	./scripts/run.sh

# Format code
fmt:
	@echo "Formatting Go code..."
	go fmt ./...
	gofmt -s -w .

# Check go mod tidy
check-go-mod:
	@echo "Checking go.mod..."
	go mod tidy
	@git diff --exit-code go.mod go.sum || (echo "go.mod or go.sum is out of date. Please run 'go mod tidy'." && exit 1)

# Run simulator
simulator: build
	@echo "Running simulator..."
	./scripts/run_simulator.sh

# Antithesis testing
antithesis-images:
	@echo "Building Antithesis images..."
	./scripts/build_antithesis_images.sh

test-antithesis: install-luxd build
	@echo "Running Antithesis tests..."
	go run ./tests/antithesis --luxd-path=/tmp/e2e-test/luxd/luxd --duration=60s

# Quick build for development
dev: build

# Full CI pipeline
ci: check-go-mod lint-all test coverage

.PHONY: build-all test-unit test-race test-e2e test-e2e-precompile test-e2e-load test-e2e-warp
.PHONY: bench coverage generate-mocks generate-codec check-generate setup docker docker-test
.PHONY: check-version install-luxd dev-shell run-local fmt check-go-mod simulator
.PHONY: antithesis-images test-antithesis dev ci
