# spacesh — local build helpers (macOS).
# `make` or `make help` lists targets.

APP_DIR         := app
TAURI_TARGET    := universal-apple-darwin
DMG_DIR         := $(APP_DIR)/src-tauri/target/$(TAURI_TARGET)/release/bundle/dmg
NATIVE_DMG_DIR  := $(APP_DIR)/src-tauri/target/release/bundle/dmg
NATIVE_TRIPLE   := $(shell rustc -vV 2>/dev/null | awk '/^host:/{print $$2}')
SIDECAR_DIR     := $(APP_DIR)/src-tauri/bin
BUNDLE_CONFIG   := src-tauri/tauri.bundle.conf.json
APP_BUNDLE      := $(APP_DIR)/src-tauri/target/$(TAURI_TARGET)/release/bundle/macos/spacesh.app
NATIVE_APP_BUNDLE := $(APP_DIR)/src-tauri/target/release/bundle/macos/spacesh.app
APP_VERSION     := $(shell node -p "require('./$(APP_DIR)/src-tauri/tauri.conf.json').version" 2>/dev/null || echo 0.0.0)

LANDING_IMAGE   := spacesh-landing
LANDING_VERSION := $(shell cat landing/VERSION 2>/dev/null || echo 0.0.0)
REGISTRY        ?= git.realmanual.ru
REPO            ?= spacesh

# ---- Prod deploy (SSH) ----
SSH_HOST        ?= 192.168.8.5
SSH_USER        ?= root
SSH_REMOTE_DIR  ?= /srv/spaceshell
SSH_KEY         ?= $(HOME)/.ssh/id_rsa
SSH_OPTS        := -i $(SSH_KEY) -o StrictHostKeyChecking=accept-new

.DEFAULT_GOAL := help

.PHONY: help
help: ## show this help
	@echo "spacesh — make targets (app v$(APP_VERSION)):"
	@grep -hE '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | \
		awk 'BEGIN{FS=":.*?## "}{printf "  \033[36m%-16s\033[0m %s\n", $$1, $$2}'

# ---- App / DMG (macOS) ----

.PHONY: deps
deps: ## install frontend deps (npm ci)
	cd $(APP_DIR) && npm ci

.PHONY: targets
targets: ## add rust targets for the universal build
	rustup target add aarch64-apple-darwin x86_64-apple-darwin

.PHONY: bump
bump: ## increment the patch version in tauri.conf.json (single source of truth)
	@node -e "const f='$(APP_DIR)/src-tauri/tauri.conf.json';const fs=require('fs');const j=JSON.parse(fs.readFileSync(f));const p=j.version.split('.').map(Number);p[2]=(p[2]||0)+1;j.version=p.join('.');fs.writeFileSync(f, JSON.stringify(j,null,2)+'\n');console.log('version → '+j.version)"

.PHONY: dmg
dmg: bump targets ## bump version + build the universal (Intel + Apple Silicon) .dmg — UNSIGNED
	# Tauri's universal build needs BOTH the per-arch sidecars (resolved during each
	# arch sub-build) AND a fat spaceshd-universal-apple-darwin (copied into the final
	# bundle — Tauri does not lipo sidecars itself). spaceshd ships inside
	# spacesh.app/Contents/MacOS else the GUI is offline.
	cargo build --release -p spaceshd --target aarch64-apple-darwin
	cargo build --release -p spaceshd --target x86_64-apple-darwin
	rm -rf $(SIDECAR_DIR) && mkdir -p $(SIDECAR_DIR)   # avoid stale sidecars poisoning the bundle
	cp target/aarch64-apple-darwin/release/spaceshd $(SIDECAR_DIR)/spaceshd-aarch64-apple-darwin
	cp target/x86_64-apple-darwin/release/spaceshd  $(SIDECAR_DIR)/spaceshd-x86_64-apple-darwin
	lipo -create -output $(SIDECAR_DIR)/spaceshd-universal-apple-darwin \
		target/aarch64-apple-darwin/release/spaceshd \
		target/x86_64-apple-darwin/release/spaceshd
	cd $(APP_DIR) && npm run tauri build -- --target $(TAURI_TARGET) --config $(BUNDLE_CONFIG)
	@echo "→ $(DMG_DIR)" && ls -lh $(DMG_DIR)/*.dmg

.PHONY: dmg-native
dmg-native: bump ## bump version + build a .dmg for the current arch only (faster)
	cargo build --release -p spaceshd
	rm -rf $(SIDECAR_DIR) && mkdir -p $(SIDECAR_DIR)   # avoid stale sidecars poisoning the bundle
	cp target/release/spaceshd $(SIDECAR_DIR)/spaceshd-$(NATIVE_TRIPLE)
	cd $(APP_DIR) && npm run tauri build -- --config $(BUNDLE_CONFIG)
	@ls -lh $(NATIVE_DMG_DIR)/*.dmg

.PHONY: app-bundle
app-bundle: ## build just the native .app (no .dmg/hdiutil — fast, for self-install)
	cargo build --release -p spaceshd
	rm -rf $(SIDECAR_DIR) && mkdir -p $(SIDECAR_DIR)
	cp target/release/spaceshd $(SIDECAR_DIR)/spaceshd-$(NATIVE_TRIPLE)
	cd $(APP_DIR) && npm run tauri build -- --bundles app --config $(BUNDLE_CONFIG)

.PHONY: dev
dev: ## run the app in dev mode (tauri dev)
	cd $(APP_DIR) && npm run tauri dev

.PHONY: daemon
daemon: ## build & run the daemon
	cargo run -p spaceshd

.PHONY: kill-daemon
kill-daemon: ## stop a running spaceshd so a freshly-built one takes over
	-pkill -x spaceshd
	-rm -f $$HOME/.spacesh/sock

.PHONY: install
install: kill-daemon ## install the native .app to /Applications, restart daemon, clear quarantine
	rm -rf /Applications/spacesh.app
	cp -R "$(NATIVE_APP_BUNDLE)" /Applications/
	xattr -dr com.apple.quarantine /Applications/spacesh.app
	@echo "Installed (native). Quit & relaunch spacesh; the bundled daemon restarts."

.PHONY: install-universal
install-universal: kill-daemon ## install the universal .app to /Applications
	rm -rf /Applications/spacesh.app
	cp -R "$(APP_BUNDLE)" /Applications/
	xattr -dr com.apple.quarantine /Applications/spacesh.app

.PHONY: reinstall
reinstall: app-bundle install ## fast self-update: build .app (no dmg), reinstall, restart daemon

# ---- Tests ----

.PHONY: test
test: ## run all tests (cargo + tsc)
	cargo test
	cd $(APP_DIR) && npx tsc --noEmit

# ---- Landing ----

.PHONY: landing-image
landing-image: ## build the landing nginx image
	docker build -t $(LANDING_IMAGE):$(LANDING_VERSION) -t $(LANDING_IMAGE):latest landing

.PHONY: landing-run
landing-run: landing-image ## serve the landing locally on http://localhost:8088
	docker run --rm -p 8088:80 $(LANDING_IMAGE):latest

.PHONY: landing-push
landing-push: landing-image ## tag & push the landing image to the registry
	docker tag $(LANDING_IMAGE):latest $(REGISTRY)/$(REPO)/$(LANDING_IMAGE):$(LANDING_VERSION)
	docker tag $(LANDING_IMAGE):latest $(REGISTRY)/$(REPO)/$(LANDING_IMAGE):latest
	docker push $(REGISTRY)/$(REPO)/$(LANDING_IMAGE):$(LANDING_VERSION)
	docker push $(REGISTRY)/$(REPO)/$(LANDING_IMAGE):latest

# ---- Prod deploy ----

.PHONY: deploy-dmg
deploy-dmg: dmg ## upload the .dmg + update manifest (latest.json) to the prod download dir
	@VER=$$(node -p "require('./$(APP_DIR)/src-tauri/tauri.conf.json').version"); \
	printf '{"version":"%s","url":"https://spaceshell.ru/download/spacesh.dmg"}\n' "$$VER" > /tmp/spacesh-latest.json; \
	echo "manifest version → $$VER"
	ssh $(SSH_OPTS) $(SSH_USER)@$(SSH_HOST) "mkdir -p $(SSH_REMOTE_DIR)/download"
	scp $(SSH_OPTS) $(DMG_DIR)/*.dmg "$(SSH_USER)@$(SSH_HOST):$(SSH_REMOTE_DIR)/download/spacesh.dmg"
	scp $(SSH_OPTS) /tmp/spacesh-latest.json "$(SSH_USER)@$(SSH_HOST):$(SSH_REMOTE_DIR)/download/latest.json"
	@echo "Uploaded → https://spaceshell.ru/download/spacesh.dmg + latest.json"

.PHONY: deploy-stack
deploy-stack: ## sync compose+proxy.conf to prod and pull/up (manual; CI does this on push)
	ssh $(SSH_OPTS) $(SSH_USER)@$(SSH_HOST) "mkdir -p $(SSH_REMOTE_DIR)/download"
	scp $(SSH_OPTS) deploy/docker-compose.yaml deploy/proxy.conf "$(SSH_USER)@$(SSH_HOST):$(SSH_REMOTE_DIR)/"
	ssh $(SSH_OPTS) $(SSH_USER)@$(SSH_HOST) "cd $(SSH_REMOTE_DIR) && docker compose pull && docker compose up -d"

# ---- Clean ----

.PHONY: clean
clean: ## remove build artifacts
	cargo clean
	rm -rf $(APP_DIR)/dist
