GODOT := $(shell command -v godot4 2>/dev/null || command -v godot 2>/dev/null)

.PHONY: help setup build check-protocol client server game stop test lint ci ci-client ci-server clean \
       decisions-sync decisions-coverage decisions-active decisions-orphan \
       db-backup db-install validate-content content-ron check-fact-ids setup-hooks \
       pre-pr pre-pr-lint pre-pr-build pre-pr-test pre-pr-validate pre-pr-fixtures \
       pre-pr-server pre-pr-client pre-pr-content \
       fixtures-client golden-diff golden-update \
       checklist-validate checklist-generate \
       perf-baseline debug-schedule \
       test-ipc-fixtures test-ipc-protocol test-ipc-integration test-ipc-benchmark

# --- Configuration ---

GODOT_VERSION ?= 4.6

# Default
help:
	@echo "The Settled Reach — Development Commands"
	@echo ""
	@echo "  make setup          Install dev dependencies (Rust, Godot, tooling)"
	@echo "  make build          Build client and server"
	@echo "  make game           Build and run the full game (server + client)"
	@echo "  make stop           Stop any running server instance"
	@echo "  make client         Run the Godot client (test mode)"
	@echo "  make server         Run the Rust simulation server"
	@echo "  make test               Run all tests"
	@echo "  make test-ipc-fixtures  Layer 1: IPC serialization fixtures"
	@echo "  make test-ipc-protocol  Layer 2: mock IPC protocol tests"
	@echo "  make test-ipc-integration Layer 3: real subprocess round-trip"
	@echo "  make test-ipc-benchmark IPC latency benchmark (blocked: #555/#556)"
	@echo "  make lint               Run all linters"
	@echo "  make ci                 Run full CI pipeline locally"
	@echo "  make ci-client          Run client CI checks"
	@echo "  make ci-server          Run server CI checks"
	@echo "  make check-protocol Verify server/client protocol versions match"
	@echo "  make clean          Remove build artifacts and caches"
	@echo ""
	@echo "  make db-backup          Backup shared database to git (main only)"
	@echo "  make db-install         Restore shared database from backup"
	@echo ""
	@echo "  make decisions-sync     Sync decisions/*.md into SQLite"
	@echo "  make decisions-coverage Decision-to-ticket coverage by domain"
	@echo "  make decisions-active   List active decisions"
	@echo "  make decisions-orphan   Decisions without implementing tickets"
	@echo "  make validate-content   Validate content YAML against schemas"
	@echo "  make check-fact-ids    Check fact_id references against knowledge catalogs"
	@echo "  make content-ron       Convert content YAML to RON (build-time)"
	@echo "  make fixtures-client    Generate GDScript->Rust cross-encoder fixtures (#475)"
	@echo "  make golden-diff        Show diff if golden file output has changed"
	@echo "  make golden-update      Regenerate golden file and stage for commit"
	@echo "  make checklist-validate Validate checklist YAML against schema"
	@echo "  make checklist-generate Validate checklists + print condition summary"
	@echo "  make perf-baseline      Run performance benchmarks and save baseline"
	@echo ""
	@echo "  make pre-pr             Run all pre-PR checks (lint, build, test, validate, fixtures)"
	@echo "  make pre-pr-server      Server-scoped pre-PR (lint, build, test, fixtures)"
	@echo "  make pre-pr-client      Client-scoped pre-PR (lint, build, test)"
	@echo "  make pre-pr-content     Content-scoped pre-PR (schema + cross-ref validation)"
	@echo ""
	@echo "  make setup-hooks       Install pre-commit hooks (included in setup)"
	@echo "  make debug-schedule    Print bevy_ecs schedule graph (diff for PR artifacts)"
	@echo ""
	@echo "  GODOT_VERSION=4.6 make setup   Override Godot version"

# --- Setup ---

setup: setup-rust setup-godot setup-tooling setup-hooks decisions-sync
	@echo "Dev environment ready."

setup-rust:
	@tooling/install-rust

setup-godot:
	@GODOT_VERSION=$(GODOT_VERSION) tooling/install-godot

setup-tooling:
	@echo "Checking tooling dependencies..."
	@command -v python3 >/dev/null 2>&1 || { echo "Install Python 3"; exit 1; }
	@command -v curl >/dev/null 2>&1 || { echo "Install curl (required for Godot download)"; exit 1; }
	@command -v unzip >/dev/null 2>&1 || { echo "Install unzip (required for Godot download)"; exit 1; }
	@python3 -c "import yaml" 2>/dev/null || { echo "Install PyYAML: pip install pyyaml"; exit 1; }
	@python3 -c "import jsonschema" 2>/dev/null || { echo "Install jsonschema: pip install jsonschema"; exit 1; }

setup-hooks:
	@git config core.hooksPath .config/hooks
	@echo "Git hooks path set to .config/hooks"

# --- Build ---

check-protocol:
	@SERVER_V=$$(grep 'pub const PROTOCOL_VERSION' server/src/bridge/types.rs | sed 's/.*= *//;s/[^0-9]//g'); \
	CLIENT_V=$$(grep 'const PROTOCOL_VERSION' client/scripts/protocol/protocol.gd | sed 's/.*= *//;s/[^0-9]//g'); \
	if [ "$$SERVER_V" != "$$CLIENT_V" ]; then \
		echo "ERROR: Protocol version mismatch — server=$$SERVER_V, client=$$CLIENT_V"; \
		echo "  Fix: update client/scripts/protocol/protocol.gd to match server/src/bridge/types.rs"; \
		exit 1; \
	fi

build: check-protocol build-server build-client

build-server:
	cd server && cargo build

build-client:
	@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
	$(GODOT) --headless --path client --import --quit

# --- Run ---

server:
	cd server && cargo run --bin settled-reach-server

client:
	@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
	$(GODOT) --path client

game: stop build
	@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
	@echo "Starting server..."
	@cd server && cargo run --bin settled-reach-server &
	@sleep 2
	@echo "Starting client..."
	@SR_LIVE=1 $(GODOT) --path client
	@$(MAKE) stop

stop:
	@lsof -ti :9876 | xargs -r kill 2>/dev/null || true
	@echo "Stopped any running server on port 9876"

# --- Test ---

test: test-server test-client

test-server:
	tests/run-rust

fixtures:
	cd server && cargo test --test gen_fixtures -- --ignored

fixtures-client:
	@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
	@echo "Generating GDScript fixtures for Rust decoder..."
	$(GODOT) --headless --path client -s res://tests/gen_client_fixtures.gd
	@echo "Verifying Rust can decode GDScript fixtures..."
	cd server && cargo test --test serialization gdscript_generated_fixtures
	@echo "--- Fixtures-client: PASS ---"

golden-diff:
	@echo "Regenerating golden output for comparison..."
	@mkdir -p .cache/golden
	@cp server/tests/golden/proof_room_tick_10.json .cache/golden/before.json
	@cd server && UPDATE_GOLDEN=1 cargo test --test golden_suite -- proof_room_tick_10_matches_golden; \
		rc=$$?; \
		cp ../server/tests/golden/proof_room_tick_10.json ../.cache/golden/after.json 2>/dev/null; \
		cp ../.cache/golden/before.json ../server/tests/golden/proof_room_tick_10.json; \
		if [ $$rc -ne 0 ]; then echo "Cargo test failed (golden file restored)."; exit $$rc; fi
	@if diff -q .cache/golden/before.json .cache/golden/after.json >/dev/null 2>&1; then \
		echo "--- Golden file: UP TO DATE ---"; \
	else \
		echo "--- Golden file has CHANGED ---"; \
		echo ""; \
		diff --color -u .cache/golden/before.json .cache/golden/after.json || true; \
		echo ""; \
		echo "Run 'make golden-update' to accept changes."; \
		exit 1; \
	fi

golden-update:
	@echo "Regenerating golden file..."
	@cd server && UPDATE_GOLDEN=1 cargo test --test golden_suite -- proof_room_tick_10_matches_golden
	@git add server/tests/golden/
	@echo "--- Golden file updated and staged ---"
	@echo "Review with: git diff --cached -- server/tests/golden/"

test-client:
	tests/run-godot

test-ipc-fixtures:
	tests/run-ipc-fixtures

test-ipc-protocol:
	tests/run-ipc-protocol

test-ipc-integration:
	tests/run-ipc-integration

test-ipc-benchmark:
	tests/run-ipc-benchmark

# --- Lint ---

lint: lint-server lint-client

lint-server:
	cd server && cargo clippy -- -D warnings
	cd server && cargo fmt --check

lint-client:
	@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
	@echo "Checking GDScript for errors..."
	@$(GODOT) --headless --path client --quit 2>&1 | grep -i "SCRIPT ERROR" && { echo "GDScript errors found"; exit 1; } || echo "No script errors found"

# --- Pre-PR verification ---

pre-pr: pre-pr-lint pre-pr-build pre-pr-test pre-pr-validate pre-pr-fixtures
	@echo ""
	@echo "=== PRE-PR: ALL CHECKS PASSED ==="
	@echo "Safe to create PR."

pre-pr-lint: lint-server lint-client
	@echo "--- Lint: PASS ---"

pre-pr-build: build-server build-client
	@echo "--- Build: PASS ---"

pre-pr-test: test-server test-client
	@echo "--- Tests: PASS ---"

pre-pr-validate: validate-content check-fact-ids
	@echo "--- Content validation: PASS ---"

pre-pr-fixtures:
	@echo "Checking Rust->GDScript fixture staleness..."
	@cd server && cargo test --test gen_fixtures -- --ignored
	@if git diff --quiet client/tests/fixtures/; then \
		echo "--- Rust fixtures: UP TO DATE ---"; \
	else \
		echo ""; \
		echo "--- RUST FIXTURES STALE ---"; \
		echo "  Protocol changed but fixtures not regenerated."; \
		echo "  Stale fixtures make all client tests FALSE POSITIVES."; \
		echo ""; \
		echo "  Changed files:"; \
		git diff --stat client/tests/fixtures/; \
		echo ""; \
		echo "  Fix: commit the updated fixtures with your protocol change."; \
		exit 1; \
	fi
	@echo "Checking GDScript->Rust fixture staleness..."
	@$(MAKE) fixtures-client
	@if git diff --quiet server/tests/fixtures/gdscript/; then \
		echo "--- GDScript fixtures: UP TO DATE ---"; \
	else \
		echo ""; \
		echo "--- GDSCRIPT FIXTURES STALE ---"; \
		echo "  Protocol changed but GDScript fixtures not regenerated."; \
		echo "  Stale fixtures make cross-encoder tests FALSE POSITIVES."; \
		echo ""; \
		echo "  Changed files:"; \
		git diff --stat server/tests/fixtures/gdscript/; \
		echo ""; \
		echo "  Fix: commit the updated fixtures with your protocol change."; \
		exit 1; \
	fi

# Branch-specific variants (faster, scope-appropriate)

pre-pr-server: lint-server build-server test-server pre-pr-fixtures
	@echo "=== Server pre-PR: PASSED ==="

pre-pr-client: lint-client build-client test-client
	@echo "=== Client pre-PR: PASSED ==="

pre-pr-content: validate-content check-fact-ids checklist-validate
	@echo "=== Content pre-PR: PASSED ==="

# --- CI (run locally) ---

ci: ci-server ci-client

ci-server: lint-server build-server test-server

ci-client: lint-client build-client test-client

# --- Database ---

db-backup:
	@tooling/db-backup

db-install:
	@tooling/db-install

# --- Decisions ---

decisions-sync:
	@db/connectors/decisions-sync

decisions-coverage:
	@db/connectors/sqlite-query "SELECT d.domain, COUNT(DISTINCT d.id) as decisions, COUNT(DISTINCT t.decision_ref) as with_tickets FROM decisions d LEFT JOIN tickets t ON d.id = t.decision_ref WHERE d.status='active' AND d.type='confirmed' GROUP BY d.domain"

decisions-active:
	@db/connectors/sqlite-query "SELECT id, domain, title FROM decisions WHERE status='active' AND type='confirmed' ORDER BY domain, id"

decisions-orphan:
	@db/connectors/sqlite-query "SELECT id, title FROM decisions WHERE type='confirmed' AND status='active' AND id NOT IN (SELECT DISTINCT decision_ref FROM tickets WHERE decision_ref IS NOT NULL)"

# --- Content Validation ---

validate-content:
	@tooling/validate-content

check-fact-ids:
	@tooling/check-fact-ids

checklist-validate:
	@tooling/validate-checklist --check

checklist-generate:
	@tooling/validate-checklist

perf-baseline:
	@tooling/perf-baseline

# --- Schedule debug (#346) ---

debug-schedule:
	@echo "Dumping bevy_ecs schedule graph..."
	@cd server && cargo run --bin settled-reach-server -- --dump-schedule

content-ron:
	cd tooling/content-converter && cargo build --release
	tooling/content-converter/target/release/content-converter --input content --output content-ron --verbose

# --- Clean ---

clean:
	cd server && cargo clean || true
	rm -rf .cache/*
	rm -rf client/.godot/* client/reports
	@echo "Clean complete."
