.PHONY: all build clean clean-all install test test-race lint fmt deps help fresh qualify-selfupdate
.PHONY: build-linux build-windows build-macos
.PHONY: build-linux-amd64 build-linux-arm64 build-win-x86_64 build-win-arm64 build-macos-intel build-macos-arm
.PHONY: build-all run release checksums
.PHONY: build-generator build-generator-linux build-generator-windows build-generator-macos
.PHONY: frontend-deps frontend-vendor frontend-vendor-check frontend
.PHONY: tailwind tailwind-watch tailwind-dev
.PHONY: release-build release-package release-checksums _release-frontend-check
.PHONY: _ensure-dist _ensure-manifest-trust _generate-windows-resources
.PHONY: build-aur

# Detect number of CPU cores for parallel builds
NPROC := $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
# Default to half the cores for parallel make (leave rest for system)
JOBS ?= $(shell echo $$(($(NPROC) > 8 ? 8 : $(NPROC))))

GOOS?=$(shell go env GOOS)
GOARCH?=$(shell go env GOARCH)

BINARY_NAME=mpv-manager
GENERATOR_NAME=generate-info
CHECKSUMS_NAME=gen-checksums
VERSION?=1.3.0-rc.17
NORMALIZED_VERSION=$(patsubst v%,%,$(strip $(VERSION)))
# Public channel trust is version-controlled; stable builds never include the RC key.
ifneq ($(findstring -,$(firstword $(subst +, ,$(NORMALIZED_VERSION)))),)
include release/rc-trust.mk
else
include release/stable-trust.mk
endif
WINDOWS_RESOURCE_VERSION=$(firstword $(subst +, ,$(firstword $(subst -, ,$(NORMALIZED_VERSION)))))
BUILD_TIME:=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
GIT_COMMIT=$(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")

# Self-update disable flag for package manager builds (Arch AUR, etc.)
# Set to disable self-update: make build SELF_UPDATE_FLAG="-X 'gitgud.io/mike/mpv-manager/pkg/version.SelfUpdateDisabled=true'"
SELF_UPDATE_FLAG?=
# Release builds inject one or more trusted Ed25519 public keys as
# "key-id=base64,key-id-2=base64". Development builds may leave this empty;
# network release metadata then fails closed.
MANIFEST_PUBLIC_KEYS?=
MANIFEST_KEY_VALIDITY?=
MANIFEST_REVOKED_KEY_IDS?=
MANIFEST_TRUST_FLAG=-X gitgud.io/mike/mpv-manager/pkg/version.ManifestPublicKeys=$(strip $(MANIFEST_PUBLIC_KEYS)) -X gitgud.io/mike/mpv-manager/pkg/version.ManifestKeyValidity=$(strip $(MANIFEST_KEY_VALIDITY)) -X gitgud.io/mike/mpv-manager/pkg/version.ManifestRevokedKeyIDs=$(strip $(MANIFEST_REVOKED_KEY_IDS))
QUALIFIER_OLD_VERSION?=1.2.99
QUALIFIER_NEW_VERSION?=1.3.0
GO_WINRES=go run github.com/tc-hib/go-winres@v0.3.3
STATICCHECK_VERSION=v0.8.1
GO_STATICCHECK=go run honnef.co/go/tools/cmd/staticcheck@$(STATICCHECK_VERSION)

LDFLAGS=-ldflags "-X gitgud.io/mike/mpv-manager/pkg/version.CurrentVersion=$(NORMALIZED_VERSION) -X gitgud.io/mike/mpv-manager/pkg/version.BuildTime=$(BUILD_TIME) -X gitgud.io/mike/mpv-manager/pkg/version.GitCommit=$(GIT_COMMIT) $(MANIFEST_TRUST_FLAG) $(SELF_UPDATE_FLAG) -s -w"
# -buildvcs=false: Skip VCS stamping (faster, we embed version via ldflags)
# -p 4: Build up to 4 packages in parallel within each build
BUILD_FLAGS=-buildvcs=false -p 4

# =============================================================================
# UTILITY TARGETS
# =============================================================================

_ensure-dist:
	@mkdir -p dist

_ensure-manifest-trust:
	@test -n "$(strip $(MANIFEST_PUBLIC_KEYS))" || \
		(echo "Release builds require MANIFEST_PUBLIC_KEYS=key-id=base64-public-key" >&2; exit 1)
	@test -n "$(strip $(MANIFEST_KEY_VALIDITY))" || \
		(echo "Release builds require MANIFEST_KEY_VALIDITY=key-id=not-before-unix:not-after-unix" >&2; exit 1)
	@MANIFEST_PUBLIC_KEYS='$(strip $(MANIFEST_PUBLIC_KEYS))' go run ./cmd/verify-manifest -keys-only

# Native updater mechanics qualification. These binaries use the current
# updater implementation with distinct synthetic identities; historical N-1/N-2
# release upgrades remain separate release gates.
qualify-selfupdate: _ensure-dist
	go build -tags selfupdate_qualification $(BUILD_FLAGS) -ldflags "-X gitgud.io/mike/mpv-manager/pkg/version.CurrentVersion=$(QUALIFIER_OLD_VERSION)" -o dist/qualify-selfupdate-old$(if $(filter windows,$(GOOS)),.exe,) ./cmd/qualify-selfupdate
	go build -tags selfupdate_qualification $(BUILD_FLAGS) -ldflags "-X gitgud.io/mike/mpv-manager/pkg/version.CurrentVersion=$(QUALIFIER_NEW_VERSION)" -o dist/qualify-selfupdate-new$(if $(filter windows,$(GOOS)),.exe,) ./cmd/qualify-selfupdate
	./dist/qualify-selfupdate-old$(if $(filter windows,$(GOOS)),.exe,) -old ./dist/qualify-selfupdate-old$(if $(filter windows,$(GOOS)),.exe,) -new ./dist/qualify-selfupdate-new$(if $(filter windows,$(GOOS)),.exe,)

# Windows resources only need to be generated once, even with parallel builds
_generate-windows-resources: _ensure-dist
	@echo "Generating Windows resources..."
	@cd cmd/mpv-manager && $(GO_WINRES) make \
		--arch amd64,arm64 \
		--product-version "$(WINDOWS_RESOURCE_VERSION)" \
		--file-version "$(WINDOWS_RESOURCE_VERSION)"
	@test -s cmd/mpv-manager/rsrc_windows_amd64.syso
	@test -s cmd/mpv-manager/rsrc_windows_arm64.syso

# =============================================================================
# MAIN BUILD TARGETS
# =============================================================================

build: _ensure-dist
	@echo "Building for $(GOOS)/$(GOARCH)..."
	@echo "Version: $(VERSION), Commit: $(GIT_COMMIT)"
	go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(BINARY_NAME) ./cmd/mpv-manager

build-linux: build-linux-amd64 build-linux-arm64

build-windows: build-win-x86_64 build-win-arm64

build-macos: build-macos-arm build-macos-intel

# =============================================================================
# PLATFORM-SPECIFIC BUILDS
# =============================================================================

build-linux-amd64: _ensure-dist
	@echo "Building for linux/amd64..."
	CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOAMD64=v2 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(BINARY_NAME)-linux-amd64 ./cmd/mpv-manager

build-linux-arm64: _ensure-dist
	@echo "Building for linux/arm64..."
	CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(BINARY_NAME)-linux-arm64 ./cmd/mpv-manager

build-win-x86_64: _ensure-dist _generate-windows-resources
	@echo "Building for windows/amd64 (x86-64-v2)..."
	CGO_ENABLED=0 GOOS=windows GOARCH=amd64 GOAMD64=v2 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(BINARY_NAME)-win-x86_64.exe ./cmd/mpv-manager

build-win-arm64: _ensure-dist _generate-windows-resources
	@echo "Building for windows/arm64..."
	CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(BINARY_NAME)-win-arm64.exe ./cmd/mpv-manager

build-macos-arm: _ensure-dist
	@echo "Building for darwin/arm64..."
	CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(BINARY_NAME)-macos-arm ./cmd/mpv-manager

build-macos-intel: _ensure-dist
	@echo "Building for darwin/amd64..."
	CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 GOAMD64=v2 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(BINARY_NAME)-macos-intel ./cmd/mpv-manager

# =============================================================================
# PACKAGE MANAGER BUILDS (self-update disabled)
# =============================================================================

# Arch Linux AUR build (self-update disabled, package manager handles updates)
build-aur: _ensure-manifest-trust _ensure-dist
	@echo "Building for Arch Linux AUR (self-update disabled)..."
	$(MAKE) build SELF_UPDATE_FLAG="-X 'gitgud.io/mike/mpv-manager/pkg/version.SelfUpdateDisabled=true'"

# =============================================================================
# GENERATOR TOOL BUILDS
# =============================================================================

build-generator: _ensure-dist
	@echo "Building generator for $(GOOS)/$(GOARCH)..."
	@echo "Version: $(VERSION), Commit: $(GIT_COMMIT)"
	CGO_ENABLED=0 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(GENERATOR_NAME) ./cmd/generate-info

build-generator-linux: build-generator-linux-amd64 build-generator-linux-arm64

build-generator-windows: build-generator-windows-amd64 build-generator-windows-arm64

build-generator-macos: build-generator-macos-amd64 build-generator-macos-arm64

build-generator-linux-amd64: _ensure-dist
	@echo "Building generator for linux/amd64..."
	CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(GENERATOR_NAME)-linux-amd64 ./cmd/generate-info

build-generator-linux-arm64: _ensure-dist
	@echo "Building generator for linux/arm64..."
	CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(GENERATOR_NAME)-linux-arm64 ./cmd/generate-info

build-generator-windows-amd64: _ensure-dist _generate-windows-resources
	@echo "Building generator for windows/amd64..."
	CGO_ENABLED=0 GOOS=windows GOARCH=amd64 GOAMD64=v2 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(GENERATOR_NAME)-windows-amd64.exe ./cmd/generate-info

build-generator-windows-arm64: _ensure-dist _generate-windows-resources
	@echo "Building generator for windows/arm64..."
	CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(GENERATOR_NAME)-windows-arm64.exe ./cmd/generate-info

build-generator-macos-amd64: _ensure-dist
	@echo "Building generator for darwin/amd64..."
	CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(GENERATOR_NAME)-macos-amd64 ./cmd/generate-info

build-generator-macos-arm64: _ensure-dist
	@echo "Building generator for darwin/arm64..."
	CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(GENERATOR_NAME)-macos-arm64 ./cmd/generate-info

build-gen-checksums: _ensure-dist
	@echo "Building gen-checksums..."
	CGO_ENABLED=0 go build $(BUILD_FLAGS) $(LDFLAGS) -o dist/$(CHECKSUMS_NAME) ./cmd/gen-checksums

# =============================================================================
# PARALLEL BUILD TARGETS
# =============================================================================

# Build all platforms in parallel (use: make -j8 build-all-parallel)
build-all-parallel: _ensure-manifest-trust _ensure-dist _generate-windows-resources
	@echo "Building all platforms in parallel with $(JOBS) jobs..."
	$(MAKE) -j$(JOBS) \
		build-linux-amd64 build-linux-arm64 \
		build-win-x86_64 build-win-arm64 \
		build-macos-intel build-macos-arm \
		build-gen-checksums  build-generator
	@echo "All builds complete:"
	@ls -lh dist/$(BINARY_NAME)-* dist/$(CHECKSUMS_NAME) 2>/dev/null || echo "  (none)"

# All platforms (sequential for safety, use build-all-parallel for speed)
all: clean
	@echo "Building all installers..."
	$(MAKE) -j$(JOBS) \
		build-linux-amd64 build-linux-arm64 \
		build-win-x86_64 build-win-arm64 \
		build-macos-intel build-macos-arm \
		build-gen-checksums build-generator
	@echo "Created binaries:"
	@ls -lh dist/$(BINARY_NAME)-* dist/$(CHECKSUMS_NAME) 2>/dev/null || echo "  (none)"

build-all: all

# =============================================================================
# RELEASE TARGETS (PARALLEL BUILDS + SEQUENTIAL PACKAGING)
# =============================================================================

# Stage 1: Build all binaries in parallel
release-build: _ensure-manifest-trust _ensure-dist _generate-windows-resources
	@echo "=== Stage 1/3: Building all binaries ($(JOBS) parallel jobs) ==="
	$(MAKE) -j$(JOBS) \
		build-linux-amd64 build-linux-arm64 \
		build-win-x86_64 build-win-arm64 \
		build-macos-intel build-macos-arm \
		build-gen-checksums

# Stage 2: Package binaries (sequential to avoid race conditions)
release-package:
	@echo "=== Stage 2/3: Creating release packages for version $(VERSION) ==="
	@rm -rf dist/.release-package
	@for package in linux-amd64 linux-arm64 win-x86_64 win-arm64 macos-intel macos-arm; do \
		mkdir -p "dist/.release-package/$$package"; \
		cp LICENSE "dist/.release-package/$$package/LICENSE"; \
		cp docs/THIRD_PARTY_NOTICES.md "dist/.release-package/$$package/THIRD_PARTY_NOTICES.md"; \
	done
	@cp dist/$(BINARY_NAME)-linux-amd64 dist/.release-package/linux-amd64/
	@cp dist/$(BINARY_NAME)-linux-arm64 dist/.release-package/linux-arm64/
	@cp dist/$(BINARY_NAME)-win-x86_64.exe dist/.release-package/win-x86_64/
	@cp dist/$(BINARY_NAME)-win-arm64.exe dist/.release-package/win-arm64/
	@cp dist/$(BINARY_NAME)-macos-intel dist/.release-package/macos-intel/
	@cp dist/$(BINARY_NAME)-macos-arm dist/.release-package/macos-arm/
	@tar -C dist/.release-package/linux-amd64 -czf dist/$(BINARY_NAME)-$(VERSION)-linux-amd64.tar.gz $(BINARY_NAME)-linux-amd64 LICENSE THIRD_PARTY_NOTICES.md
	@tar -C dist/.release-package/linux-arm64 -czf dist/$(BINARY_NAME)-$(VERSION)-linux-arm64.tar.gz $(BINARY_NAME)-linux-arm64 LICENSE THIRD_PARTY_NOTICES.md
	@cd dist/.release-package/win-x86_64 && zip -q ../../../dist/$(BINARY_NAME)-$(VERSION)-win-x86_64.zip $(BINARY_NAME)-win-x86_64.exe LICENSE THIRD_PARTY_NOTICES.md
	@cd dist/.release-package/win-arm64 && zip -q ../../../dist/$(BINARY_NAME)-$(VERSION)-win-arm64.zip $(BINARY_NAME)-win-arm64.exe LICENSE THIRD_PARTY_NOTICES.md
	@cd dist/.release-package/macos-intel && zip -q ../../../dist/$(BINARY_NAME)-$(VERSION)-macos-intel.zip $(BINARY_NAME)-macos-intel LICENSE THIRD_PARTY_NOTICES.md
	@cd dist/.release-package/macos-arm && zip -q ../../../dist/$(BINARY_NAME)-$(VERSION)-macos-arm.zip $(BINARY_NAME)-macos-arm LICENSE THIRD_PARTY_NOTICES.md
	@for archive in dist/$(BINARY_NAME)-$(VERSION)-linux-*.tar.gz; do \
		tar -tzf "$$archive" | grep -Fx LICENSE >/dev/null; \
		tar -tzf "$$archive" | grep -Fx THIRD_PARTY_NOTICES.md >/dev/null; \
	done
	@for archive in dist/$(BINARY_NAME)-$(VERSION)-*.zip; do \
		unzip -Z1 "$$archive" | grep -Fx LICENSE >/dev/null; \
		unzip -Z1 "$$archive" | grep -Fx THIRD_PARTY_NOTICES.md >/dev/null; \
	done
	@rm -rf dist/.release-package

# Stage 3: Generate checksums
release-checksums:
	@echo "=== Stage 3/3: Generating BLAKE3 checksums ==="
	./dist/$(CHECKSUMS_NAME)
	@echo "Release packages created:"
	@ls -lh dist/*$(VERSION)* dist/BLAKE3SUMS.txt

# Full release: clean + parallel build + package + checksum
# .NOTPARALLEL: prerequisites run in order even under make -jN, so `clean`
# cannot race with builds writing to dist/. Parallelism still happens inside
# release-build via its own $(MAKE) -j$(JOBS); other targets stay parallel.
.NOTPARALLEL: release
release: _ensure-manifest-trust _release-frontend-check clean release-build release-package release-checksums

_release-frontend-check:
	@echo "Verifying locked frontend inputs before release..."
	npm ci
	npm run vendor:frontend:check
	npm test
	@task_css=$$(mktemp); \
		trap 'rm -f "$$task_css"' EXIT; \
		npx tailwindcss -i ./internal/webassets/css/input.css -o "$$task_css" --minify; \
		diff "$$task_css" internal/webassets/static/css/tailwind.min.css

checksums: build-gen-checksums
	@echo "Creating BLAKE3 checksums..."
	./dist/$(CHECKSUMS_NAME)

# =============================================================================
# DEVELOPMENT TARGETS
# =============================================================================

clean:
	@echo "Cleaning build artifacts..."
	@rm -rf dist/*
	@rm -rf dist/.release-package
	@echo "Clean complete"

clean-all:
	@echo "Deep cleaning (includes Go build cache)..."
	@rm -rf dist/*
	@go clean -cache
	@echo "Deep clean complete"

install: build
	@echo "Installing $(BINARY_NAME) to GOPATH/bin..."
	@go install $(LDFLAGS) ./cmd/mpv-manager
	@echo "Installation complete"

test:
	@echo "Running tests with $(JOBS) parallel packages..."
	go test -v -p $(JOBS) ./...

test-coverage:
	@echo "Running tests with coverage..."
	go test -v -p $(JOBS) -coverprofile=coverage.out ./...
	go tool cover -html=coverage.out -o coverage.html
	@echo "Coverage report: coverage.html"

test-race:
	@echo "Running tests with race detector..."
	go test -v -race -p $(JOBS) ./...

lint:
	@echo "Running vet and pinned Staticcheck correctness analyzers..."
	go vet ./...
	$(GO_STATICCHECK) -checks='SA*' ./...

fmt:
	@echo "Formatting code..."
	@go fmt ./...
	@if command -v goimports >/dev/null 2>&1; then \
		goimports -w .; \
	fi

deps:
	@echo "Downloading dependencies..."
	go mod download
	go mod tidy
	@echo "Dependencies ready"

deps-update:
	@echo "Updating dependencies..."
	go get -u ./...
	go mod tidy
	@echo "Dependencies updated"

vendor:
	@echo "Vendoring dependencies..."
	go mod vendor

first-time:
	@echo "Setting up for first time use..."
	@$(MAKE) deps
	@$(MAKE) build
	@echo ""
	@echo "Setup complete! Binary: dist/$(BINARY_NAME)"
	@echo "Run with: ./dist/$(BINARY_NAME)"

fresh:
	@echo "Fresh build (clean + deps + build)..."
	@$(MAKE) clean
	@$(MAKE) deps
	@$(MAKE) build
	@echo ""
	@echo "Fresh build complete! Binary: dist/$(BINARY_NAME)"

run: build
	./dist/$(BINARY_NAME)

# =============================================================================
# FRONTEND ASSETS
# =============================================================================

frontend-deps:
	@echo "Installing locked frontend dependencies..."
	npm ci

frontend-vendor:
	@echo "Synchronizing package-managed browser assets..."
	npm run vendor:frontend

frontend-vendor-check:
	@echo "Checking package-managed browser assets..."
	npm run vendor:frontend:check

frontend:
	@echo "Building all committed frontend assets..."
	npm run frontend:build

tailwind:
	@echo "Building TailwindCSS..."
	npm run tailwind
	@echo "TailwindCSS build complete"

tailwind-watch:
	@echo "Watching TailwindCSS for changes..."
	npm run tailwind:watch

tailwind-dev:
	@echo "Building TailwindCSS (development - unminified)..."
	npm run tailwind:dev

# =============================================================================
# HELP
# =============================================================================

help:
	@echo "MPV.Rocks Manager Makefile"
	@echo ""
	@echo "Detected: $(NPROC) CPU cores, using $(JOBS) parallel jobs"
	@echo ""
	@echo "Quick Start:"
	@echo "  make first-time       - Install deps and build (for new clones)"
	@echo "  make build            - Build for current platform"
	@echo "  make run              - Build and run"
	@echo ""
	@echo "Parallel Builds (FAST):"
	@echo "  make build-all-parallel - Build ALL platforms in parallel"
	@echo "  make release           - Full release (parallel builds)"
	@echo "  make -j8 release       - Override parallelism (8 jobs)"
	@echo ""
	@echo "Sequential Builds (SAFE):"
	@echo "  make all               - Build all platforms"
	@echo "  make build-linux       - Linux (amd64 + arm64)"
	@echo "  make build-windows     - Windows (x86_64 + arm64)"
	@echo "  make build-macos       - macOS (intel + arm)"
	@echo ""
	@echo "Single Platform:"
	@echo "  make build-linux-amd64   - Linux x86_64"
	@echo "  make build-linux-arm64   - Linux ARM64"
	@echo "  make build-win-x86_64    - Windows x86_64"
	@echo "  make build-win-arm64     - Windows ARM64"
	@echo "  make build-macos-intel   - macOS Intel"
	@echo "  make build-macos-arm     - macOS Apple Silicon"
	@echo ""
	@echo "Package Manager Builds:"
	@echo "  make build-aur           - Arch Linux AUR (self-update disabled)"
	@echo ""
	@echo "Development:"
	@echo "  make test             - Run tests"
	@echo "  make test-race        - Run tests with race detector"
	@echo "  make test-coverage    - Tests with coverage report"
	@echo "  make lint             - Run linters"
	@echo "  make fmt              - Format code"
	@echo "  make clean            - Clean dist/ (keep cache)"
	@echo "  make clean-all        - Deep clean (includes Go cache)"
	@echo "  make frontend-deps    - Install exact frontend dependencies from package-lock.json"
	@echo "  make frontend         - Sync htmx/Alpine and rebuild Tailwind"
	@echo "  make frontend-vendor-check - Verify committed htmx/Alpine assets match npm"
	@echo ""
	@echo "Customization:"
	@echo "  JOBS=4 make release      - Use 4 parallel jobs"
	@echo "  VERSION=1.0.0 make       - Set version"
	@echo "  MANIFEST_PUBLIC_KEYS='release-id=base64' MANIFEST_KEY_VALIDITY='release-id=not-before:not-after' make build - Trust signed release metadata"
	@echo "  make build SELF_UPDATE_FLAG=\"-X 'gitgud.io/mike/mpv-manager/pkg/version.SelfUpdateDisabled=true'\" - Disable self-update"

.DEFAULT_GOAL := help
