# ABOUTME: Build automation for Sendspin Protocol server and player
# ABOUTME: Provides targets for building, testing, and cleaning binaries

.PHONY: all build player server test test-verbose test-coverage lint clean install \
	build-all build-linux build-darwin help conformance \
	install-daemon uninstall-daemon \
	install-player-daemon uninstall-player-daemon \
	install-server-daemon uninstall-server-daemon

# Version from git tag or default
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
LDFLAGS := -X github.com/Sendspin/sendspin-go/internal/version.Version=$(VERSION)

# Build with -tags=nolibopusfile so gopkg.in/hraban/opus.v2 doesn't link
# libopusfile. Our code never calls the opus.Stream API (the only consumer
# of the opusfile parts), so the linkage was free runtime-dependency weight.
# Override on the command line if you actually need opusfile (e.g. for
# upstream stream_test.go): make BUILDTAGS= test
BUILDTAGS ?= nolibopusfile
export GOFLAGS = -tags=$(BUILDTAGS)

# Default target
all: build

# Build both player and server
build: player server

# Build the player
player:
	@echo "Building sendspin-player..."
	go build -ldflags "$(LDFLAGS)" -o sendspin-player .

# Build the server
server:
	@echo "Building sendspin-server..."
	go build -ldflags "$(LDFLAGS)" -o sendspin-server ./cmd/sendspin-server

# Run tests
test:
	@echo "Running tests..."
	go test ./...

# Run tests with verbose output
test-verbose:
	@echo "Running tests (verbose)..."
	go test -v ./...

# Run tests with coverage
test-coverage:
	@echo "Running tests with coverage..."
	go test -v -race -coverprofile=coverage.out -covermode=atomic ./...
	go tool cover -html=coverage.out -o coverage.html
	@echo "Coverage report: coverage.html"

# Run linter
lint:
	@echo "Running golangci-lint..."
	@which golangci-lint > /dev/null || (echo "golangci-lint not installed. Install: https://golangci-lint.run/usage/install/" && exit 1)
	golangci-lint run --timeout=5m

# Clean built binaries and artifacts
clean:
	@echo "Cleaning binaries and artifacts..."
	rm -f sendspin-player sendspin-server resonate-player resonate-server
	rm -rf bin/
	rm -f coverage.out coverage.html

# Install both binaries to GOPATH/bin
install:
	@echo "Installing binaries..."
	go install -ldflags "$(LDFLAGS)" .
	go install -ldflags "$(LDFLAGS)" ./cmd/sendspin-server

# Build all platforms (like CI)
build-all: build-linux build-darwin

# Build Linux binaries
build-linux:
	@echo "Building Linux binaries..."
	@mkdir -p bin
	GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-player-linux-amd64 .
	GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-player-linux-arm64 .
	GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-server-linux-amd64 ./cmd/sendspin-server
	GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-server-linux-arm64 ./cmd/sendspin-server

# Build macOS binaries
build-darwin:
	@echo "Building macOS binaries..."
	@mkdir -p bin
	GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-player-darwin-amd64 .
	GOOS=darwin GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-player-darwin-arm64 .
	GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-server-darwin-amd64 ./cmd/sendspin-server
	GOOS=darwin GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-server-darwin-arm64 ./cmd/sendspin-server

# Install sendspin-player as a systemd daemon
install-player-daemon: player
	@echo "Installing sendspin-player daemon..."
	install -m 755 sendspin-player /usr/local/bin/sendspin-player
	install -m 644 dist/systemd/sendspin-player.service /etc/systemd/system/sendspin-player.service
	@if [ ! -f /etc/default/sendspin-player ]; then \
		install -m 644 dist/systemd/sendspin-player.env /etc/default/sendspin-player; \
		echo "Created /etc/default/sendspin-player — edit this file to configure."; \
	else \
		echo "/etc/default/sendspin-player already exists, not overwriting."; \
	fi
	@if [ ! -f /etc/sendspin/player.yaml ]; then \
		install -d -m 755 /etc/sendspin; \
		install -m 644 dist/config/player.example.yaml /etc/sendspin/player.yaml; \
		echo "Created /etc/sendspin/player.yaml — edit this file to configure."; \
	else \
		echo "/etc/sendspin/player.yaml already exists, not overwriting."; \
	fi
	systemctl daemon-reload
	@echo ""
	@echo "Installed. To start:"
	@echo "  sudo systemctl enable --now sendspin-player"
	@echo ""
	@echo "Configure via /etc/sendspin/player.yaml (preferred) or /etc/default/sendspin-player"

# Install sendspin-server as a systemd daemon
install-server-daemon: server
	@echo "Installing sendspin-server daemon..."
	install -m 755 sendspin-server /usr/local/bin/sendspin-server
	install -m 644 dist/systemd/sendspin-server.service /etc/systemd/system/sendspin-server.service
	@if [ ! -f /etc/default/sendspin-server ]; then \
		install -m 644 dist/systemd/sendspin-server.env /etc/default/sendspin-server; \
		echo "Created /etc/default/sendspin-server — edit this file to configure."; \
	else \
		echo "/etc/default/sendspin-server already exists, not overwriting."; \
	fi
	@if [ ! -f /etc/sendspin/server.yaml ]; then \
		install -d -m 755 /etc/sendspin; \
		install -m 644 dist/config/server.example.yaml /etc/sendspin/server.yaml; \
		echo "Created /etc/sendspin/server.yaml — edit this file to configure."; \
	else \
		echo "/etc/sendspin/server.yaml already exists, not overwriting."; \
	fi
	systemctl daemon-reload
	@echo ""
	@echo "Installed. To start:"
	@echo "  sudo systemctl enable --now sendspin-server"
	@echo ""
	@echo "Configure via /etc/sendspin/server.yaml (preferred) or /etc/default/sendspin-server"

# Aggregate: install both binaries as systemd daemons
install-daemon: install-player-daemon install-server-daemon

# Uninstall the sendspin-player systemd daemon
uninstall-player-daemon:
	@echo "Removing sendspin-player daemon..."
	-systemctl stop sendspin-player 2>/dev/null
	-systemctl disable sendspin-player 2>/dev/null
	rm -f /etc/systemd/system/sendspin-player.service
	rm -f /usr/local/bin/sendspin-player
	systemctl daemon-reload
	@echo "Removed. /etc/default/sendspin-player and /etc/sendspin/player.yaml left in place (manual cleanup if desired)."

# Uninstall the sendspin-server systemd daemon
uninstall-server-daemon:
	@echo "Removing sendspin-server daemon..."
	-systemctl stop sendspin-server 2>/dev/null
	-systemctl disable sendspin-server 2>/dev/null
	rm -f /etc/systemd/system/sendspin-server.service
	rm -f /usr/local/bin/sendspin-server
	systemctl daemon-reload
	@echo "Removed. /etc/default/sendspin-server and /etc/sendspin/server.yaml left in place (manual cleanup if desired)."

# Aggregate: uninstall both daemons
uninstall-daemon: uninstall-player-daemon uninstall-server-daemon

# Conformance test suite — runs the Sendspin protocol conformance harness
# against the local sendspin-go checkout. Mirrors what CI does so contributors
# and conformance maintainers can reproduce CI results locally.
#
# Assumes the conformance repo is checked out at ../conformance. Clones it
# (and the aiosendspin reference peer) on first run. The CONFORMANCE_REPO_SENDSPIN_GO
# env var points the harness at this checkout instead of the managed clone.
conformance:
	@command -v uv >/dev/null 2>&1 || { echo "uv is required: https://docs.astral.sh/uv/getting-started/installation/"; exit 1; }
	@command -v git >/dev/null 2>&1 || { echo "git is required"; exit 1; }
	@if [ ! -d ../conformance ]; then \
		echo "Cloning Sendspin/conformance into ../conformance..."; \
		git clone --depth 1 https://github.com/Sendspin/conformance.git ../conformance; \
	fi
	@mkdir -p ../conformance/repos
	@if [ ! -e ../conformance/repos/aiosendspin ]; then \
		echo "Cloning aiosendspin reference peer..."; \
		git clone --depth 1 https://github.com/Sendspin/aiosendspin.git ../conformance/repos/aiosendspin; \
	fi
	@if [ ! -e ../conformance/repos/sendspin-cli ]; then \
		echo "Cloning sendspin-cli (supplies the FLAC test fixture)..."; \
		git clone --depth 1 https://github.com/Sendspin/sendspin-cli.git ../conformance/repos/sendspin-cli; \
	fi
	@cd ../conformance && uv sync
	@cd ../conformance && CONFORMANCE_REPO_SENDSPIN_GO="$(CURDIR)" uv run python scripts/run_all.py \
		--from sendspin-go \
		--to aiosendspin,sendspin-go \
		--results-dir results/
	@echo ""
	@echo "Conformance report: $(CURDIR)/../conformance/results/index.html"
	@echo "Raw results:        $(CURDIR)/../conformance/results/data/"

# Show help
help:
	@echo "Sendspin Protocol - Build Targets"
	@echo ""
	@echo "  make              - Build player and server"
	@echo "  make player       - Build sendspin-player"
	@echo "  make server       - Build sendspin-server"
	@echo "  make test         - Run tests"
	@echo "  make test-verbose - Run tests with verbose output"
	@echo "  make test-coverage- Run tests with coverage report"
	@echo "  make lint         - Run golangci-lint"
	@echo "  make clean        - Remove built binaries"
	@echo "  make install      - Install to GOPATH/bin"
	@echo "  make build-all    - Build all platforms"
	@echo "  make build-linux  - Build Linux binaries"
	@echo "  make build-darwin - Build macOS binaries"
	@echo "  make install-daemon           - Install both player and server as systemd daemons (Linux, requires root)"
	@echo "  make install-player-daemon    - Install only the player daemon"
	@echo "  make install-server-daemon    - Install only the server daemon"
	@echo "  make uninstall-daemon         - Remove both daemons"
	@echo "  make uninstall-player-daemon  - Remove only the player daemon"
	@echo "  make uninstall-server-daemon  - Remove only the server daemon"
	@echo "  make conformance  - Run protocol conformance suite (clones ../conformance on first run)"
	@echo ""
	@echo "Version: $(VERSION)"
