.PHONY: help setup check build fmt format fmt-check lint test \
        ci-format ci-lint ci-lockfile-diff ci-check ci-test ci-coverage ci-e2e ci-audit ci-changelog ci-build-check ci-release-readiness \
        install-nextest install-llvm-cov \
        e2e-up e2e-down e2e-logs e2e-run clean pre-commit lockfile

.DEFAULT_GOAL := help

CARGO := $(shell which cargo 2>/dev/null || echo $(HOME)/.cargo/bin/cargo)

# Colors
GREEN  := \033[32m
YELLOW := \033[33m
RESET  := \033[0m

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

# =============================================================================
# Dev environment
# =============================================================================

setup: ## Install rustfmt + clippy
	rustup component add rustfmt clippy

# =============================================================================
# Build & check
# =============================================================================

check: ## Cargo check (fast compile check)
	$(CARGO) check --workspace

build: ## Build all crates
	$(CARGO) build --workspace

# =============================================================================
# Code quality
# =============================================================================

fmt: ## Format all code
	$(CARGO) fmt --all

format: fmt

fmt-check: ## Check formatting (fails if not formatted)
	@echo "$(YELLOW)Checking formatting...$(RESET)"
	$(CARGO) fmt --all -- --check
	@echo "$(GREEN)✅ Formatting OK$(RESET)"

lint: ## Clippy — warnings are errors
	@echo "$(YELLOW)Running clippy...$(RESET)"
	$(CARGO) clippy --workspace -- -D warnings
	@echo "$(GREEN)✅ Clippy clean$(RESET)"

# =============================================================================
# Tests
# =============================================================================

install-nextest: ## Install cargo-nextest
	@$(CARGO) install cargo-nextest --version 0.9.114 --locked 2>/dev/null || true

install-llvm-cov: ## Install cargo-llvm-cov
	@$(CARGO) install cargo-llvm-cov --locked 2>/dev/null || true

test: fmt-check lint install-nextest ## Run all tests (local)
	$(CARGO) nextest run --workspace
	@echo "$(GREEN)✅ All tests passed$(RESET)"

# =============================================================================
# CI targets (called directly from Forgejo Actions)
# =============================================================================

ci-format: ## CI: format check
	$(CARGO) fmt --all -- --check

ci-lint: ## CI: clippy strict (--all-features so feature-gated code is exercised)
	$(CARGO) clippy --workspace --all-features --all-targets -- -D warnings

ci-lockfile-diff: ## CI: assert committed Cargo.lock matches resolution (ADR-0021)
	@cp Cargo.lock Cargo.lock.committed
	@$(CARGO) generate-lockfile
	@diff Cargo.lock.committed Cargo.lock || { \
		echo ""; \
		echo "ERROR: Cargo.lock is out of date. Run: cargo generate-lockfile && git add Cargo.lock"; \
		mv Cargo.lock.committed Cargo.lock; exit 1; }
	@mv Cargo.lock.committed Cargo.lock

ci-check: ci-format ci-lint ## CI: format + lint (stage 1)
	@echo "$(GREEN)✅ All code quality checks passed$(RESET)"

ci-test: ## CI: run unit tests with nextest
	# Exclude `integration-tests` feature (needs a live collector on :4317).
	# All other compile-time features are exercised by `ci-lint --all-features`.
	RUSTFLAGS="-D warnings" $(CARGO) nextest run --workspace \
		--features grpc,http,axum,testing,grpc-mtls

ci-build-check: ## Pre-push compile gate: workspace + all feature combinations
	$(CARGO) check --workspace --all-targets
	$(CARGO) check --workspace --all-targets --all-features
	$(CARGO) check --workspace --all-targets --no-default-features
	$(CARGO) check --workspace --all-targets --no-default-features --features http
	$(CARGO) check --workspace --all-targets --no-default-features --features grpc
	$(CARGO) check --workspace --all-targets --no-default-features --features grpc-mtls

ci-release-readiness: ## Pre-release sanity (no-op: single-crate lib, no SDK to validate)
	@echo "otel-bootstrap: single-crate lib — nothing to validate here"

ci-coverage: ## CI: coverage gate
	# Excluded lines:
	#   1. The `None => builder` arm in `init_telemetry_with_sampler` — semantically
	#      a no-op (keeps the default builder); covering it would just duplicate
	#      `init_telemetry` tests.
	#   2-12. The `grpc-mtls` code paths (with_mtls(), MtlsMaterial Debug redact,
	#      build_tls_config helper, the 3 with_tls_config conditionals) — exercising
	#      these requires a mTLS gRPC test server, scheduled as follow-up work in
	#      the rotation-watcher PR.
	#   Threshold bumped from 1 → 12. See CHANGELOG 2.1.0 for context.
	RUSTFLAGS="-D warnings" $(CARGO) llvm-cov nextest --workspace \
		--features integration-tests,grpc-mtls \
		--fail-uncovered-lines 30

ci-e2e: ## CI: e2e tests (requires OTel Collector on :4317)
	RUSTFLAGS="-D warnings" $(CARGO) nextest run \
		--features integration-tests \
		--test e2e

ci-audit: ## CI: security audit
	$(CARGO) audit --deny warnings --deny unsound --deny unmaintained --deny yanked $(if $(DB_PATH),--db $(DB_PATH) --no-fetch,)

# =============================================================================
# Security
# =============================================================================

audit: ## Run cargo-audit for known CVEs
	$(CARGO) audit

# =============================================================================
# E2E local (mirrors CI exactly)
# =============================================================================

e2e-up: ## Start OTel Collector for e2e tests
	docker compose up -d
	@echo "$(GREEN)OTel Collector running — gRPC on :4317$(RESET)"

e2e-down: ## Stop OTel Collector
	docker compose down

e2e-logs: ## Tail OTel Collector logs
	docker compose logs -f

e2e-run: e2e-up ## Full e2e: start collector + run integration tests
	$(CARGO) test --features integration-tests --test e2e
	@echo "$(GREEN)✅ E2E tests passed$(RESET)"

# =============================================================================
# Gates
# =============================================================================

lockfile: ## generate lockfile
	cargo generate-lockfile

pre-commit: ci-format ci-lint ci-lockfile-diff ci-test ci-changelog ## Run all pre-commit checks (ADR-0021)

clean: ## Remove build artifacts
	$(CARGO) clean

.PHONY: ci-changelog
ci-changelog: ## CI: verify CHANGELOG.md has entry for current package version (ADR-0021)
	@bash -lc 'bash <(curl -fsSL https://raw.githubusercontent.com/brefwiz/shared-ci-workflows/main/scripts/check-release-changelog.sh)'
