# Pineapple 顶层 Makefile —— 全仓任务的统一入口。
#
# 设计要点:
#   - 多语言异构(apple Python / pine-go Go / pine-java Java / pine-cpp C++)。
#     顶层 target 透传到 scripts/*.sh 或子目录构建系统(go / mvn / cmake)。
#   - 不内联多步命令: 所有具体步骤仍位于 scripts/*.sh,Makefile 只做命名与组合。
#   - target 命名与 wangshu Makefile 对齐(fmt/lint/test/bench/fuzz/cover/tidy/hooks/all),
#     避免双 muscle memory; 多语言专属 target 走 <lang>-<verb> 形式。
#   - `all` 名义对齐但语义有意收窄:wangshu `all` 是 `fmt lint test fuzz
#     conformance difftest bench-test`(单语言可全检);本仓 `all` 是
#     `fmt-check lint test codegen-check`,跨语言慢 job(fuzz / cross-validate /
#     differential-fuzz / cpp 系列)走显式 target,避免本地 `make all` 阻塞 1h+。
#     完整全检走 `make all && make fuzz && make cross-validate && make differential-fuzz`。

# bash 语法(process substitution / array)需要,默认 /bin/sh 会报 syntax error。
SHELL := /bin/bash

# 默认 -j 并发数(本机 12 核)。CI 上以 `make <target> PARALLEL=$(nproc)` 覆盖。
# 禁止 cmake/make 裸 -j: 无上界会触发 OOM swap 风暴(本仓 feedback)。
PARALLEL ?= 12

.PHONY: help all \
        fmt fmt-check \
        lint \
        test go-test apple-test java-test cpp-test \
        bench go-bench java-bench bench-cross-runtime bench-lua-backends \
        fuzz go-fuzz java-fuzz differential-fuzz \
        cover go-cover java-cover \
        codegen codegen-check \
        cross-validate \
        hooks tidy clean \
        bump tag-release check-pr-ci

# 默认 target: 输出帮助。"裸跑 make"不会触发任何动作,避免误操作。
help:
	@awk 'BEGIN {FS=":.*##"; printf "Pineapple targets (run \033[36mmake <target>\033[0m):\n\n"} \
	     /^[a-zA-Z_-]+:.*?##/ {printf "  \033[36m%-22s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

# ------- 复合 target ----------------------------------------------------------

all: fmt-check lint test codegen-check ## 本地提交前全检(不含跨语言慢 job:cross-validate / differential-fuzz / fuzz)

# ------- 格式化 ---------------------------------------------------------------

fmt: ## 各语言格式化(写回; gofmt / clang-format / ruff format / mvn)
	@cd pine-go && gofmt -w $$(git ls-files '*.go' 2>/dev/null || find . -name '*.go' -not -path './vendor/*')
	@if command -v clang-format >/dev/null 2>&1; then \
	    find pine-cpp -type d \( -name 'build' -o -name 'build-*' \) -prune \
	        -o -type f \( -name '*.cpp' -o -name '*.hpp' \) -print0 \
	      | xargs -0 -r clang-format -i; \
	  fi
	@if command -v ruff >/dev/null 2>&1; then ruff format apple/; fi

fmt-check: ## 格式 dry-run(CI 用; 任何 diff 即 fail)
	@out=$$(cd pine-go && gofmt -l $$(git ls-files '*.go')); \
	  if [ -n "$$out" ]; then echo "gofmt diff in:"; echo "$$out"; exit 1; fi
	@find pine-cpp -type d \( -name 'build' -o -name 'build-*' \) -prune \
	    -o -type f \( -name '*.cpp' -o -name '*.hpp' \) -print0 \
	  | xargs -0 -r clang-format --dry-run --Werror

# ------- Lint -----------------------------------------------------------------

lint: ## 全语言 lint(ruff / golangci-lint / checkstyle / clang-format)
	bash scripts/lint.sh

# ------- Test -----------------------------------------------------------------

test: ## go + apple + java 测试(test-all.sh)
	bash scripts/test-all.sh

go-test: ## 仅 pine-go 测试
	bash scripts/go-test.sh

apple-test: ## 仅 apple Python 测试
	@if [ -f .venv/bin/activate ]; then . .venv/bin/activate; fi; \
	python3 -m pytest apple/tests/ -v

java-test: ## 仅 pine-java 测试
	bash scripts/java-test.sh

cpp-test: ## 仅 pine-cpp 测试(CMake + ctest; 并发数由 PARALLEL 控制)
	bash scripts/cpp-test.sh PARALLEL=$(PARALLEL)

# ------- Coverage -------------------------------------------------------------

cover: go-cover java-cover ## 各语言覆盖率产物

go-cover: ## pine-go coverprofile + 终端 func 摘要
	cd pine-go && go test -coverprofile=coverage.out -covermode=atomic ./...
	cd pine-go && go tool cover -func=coverage.out | tail -1

java-cover: ## pine-java Jacoco 报告
	cd pine-java && mvn test -B -q jacoco:report

# ------- Benchmark ------------------------------------------------------------

bench: go-bench java-bench ## 各语言 benchmark(单语言串行; 跨引擎请用 bench-cross-runtime)

go-bench: ## pine-go go test -bench
	bash scripts/go-bench.sh

java-bench: ## pine-java fixture benchmark
	bash scripts/java-bench.sh

bench-cross-runtime: ## 跨引擎 benchmark(三引擎 × 多 fixture; 需 hey + Go/Java/C++ toolchain)
	bash scripts/bench-cross-runtime.sh

# wangshu vs gopher-lua 后端对比 benchmark:同机串行连跑两后端 + benchstat。
# 默认裁判 fixture 是 realistic_for_you_calibrated(见 benchmark-hygiene.md)。
# 需 benchstat: go install golang.org/x/perf/cmd/benchstat@latest
bench-lua-backends: ## wangshu vs gopher-lua on realistic_*_calibrated(benchstat delta)
	bash scripts/bench-lua-backends.sh

# ------- Fuzz -----------------------------------------------------------------

fuzz: go-fuzz java-fuzz ## 各语言 fuzz 30s 冒烟

go-fuzz: ## pine-go 自动发现 func Fuzz* 各跑 30s
	bash scripts/go-fuzz.sh 30s

java-fuzz: ## pine-java Jazzer fuzz 60s
	bash scripts/java-fuzz.sh 60

differential-fuzz: ## 三引擎差分 fuzz(默认 1000 轮 Go vs Java)
	bash scripts/differential-fuzz.sh

# ------- Codegen --------------------------------------------------------------

codegen: ## 从 pine-go Registry 生成 apple_generated/ + doc/operators/
	bash scripts/codegen.sh

codegen-check: codegen ## CI 用:codegen 后 git diff --exit-code(确保产物新鲜)
	git diff --exit-code apple_generated/ doc/operators/

# ------- Cross-validate -------------------------------------------------------

cross-validate: ## 19 section 跨引擎对等校验(parallel; 见 scripts/cross-validate/)
	bash scripts/cross-validate.sh

# ------- 工程基建 -------------------------------------------------------------

hooks: ## 安装 git hooks(一次性; 等价 git config core.hooksPath .githooks)
	git config core.hooksPath .githooks
	@echo "hooks installed: $$(git config core.hooksPath)"

tidy: ## go mod tidy(主 module + benchmarks 子 module) + git diff 守门(pine-java/pine-cpp 由 mvn/CMake 自管,无对应概念)
	cd pine-go && go mod tidy
	cd pine-go/benchmarks && go mod tidy
	git diff --exit-code pine-go/go.mod pine-go/go.sum pine-go/benchmarks/go.mod pine-go/benchmarks/go.sum

clean: ## 清理 pine-go / pine-cpp / pine-java build 产物
	cd pine-go && go clean -testcache -cache
	rm -rf pine-cpp/build pine-cpp/build-*
	cd pine-java && mvn -B -q clean

# ------- Release / 诊断 ------------------------------------------------------

bump: ## 跨 5 处同步版本号 + 全验(用法: make bump VERSION=0.10.0)
ifndef VERSION
	$(error VERSION not set; usage: make bump VERSION=0.10.0)
endif
	bash scripts/bump-version.sh $(VERSION)

tag-release: ## 校验 4 处版本号一致 + 创建并推送 vX.Y.Z + pine-go/vX.Y.Z 双 tag
	bash scripts/tag-release.sh

check-pr-ci: ## 阻塞等当前 PR 的 CI(并报告 review 活动 / 未解决线程);.githooks/pre-push 已自动调用,本 target 仅作手动诊断入口
	bash scripts/check-pr-ci.sh
