# macOS ships GNU Make 3.81, which ignores .ONESHELL — so the `dev` recipe is one
# shell line (\-joined) to keep the trap + background jobs in a single shell.
SHELL := /bin/bash

TOKEN      ?= devtoken
CLOUD_PORT ?= 8770
CLOUD_URL  := http://127.0.0.1:$(CLOUD_PORT)
# cloud_api.py is Postgres-backed (Phase 3). `make pg` spins a local one (persistent volume).
# This is the LOCAL default; the *-prod targets swap in DATABASE_URL_PROD instead.
# Host port 5433 (not 5432) to dodge any host-native Postgres already on 5432 — on macOS the
# native one wins on 127.0.0.1 IPv4 and you get "role postgres does not exist".
DATABASE_URL ?= postgres://postgres:pw@127.0.0.1:5433/gcontext
# Prod connection string lives in .env (DATABASE_URL_PROD=postgres://...), kept out of git.
# The *-prod targets pass it as DATABASE_URL so the same server/migrate code hits prod.
DATABASE_URL_PROD := $(shell grep -E '^DATABASE_URL_PROD=' .env 2>/dev/null | head -1 | cut -d= -f2-)


# Create tunnel with: gcloud compute ssh maat-agent --zone europe-west1-b --tunnel-through-iap -- -L 5439:127.0.0.1:5432 -N
# VM connection string, also in .env (DATABASE_URL_VM=postgres://...@127.0.0.1:5439/...).
# Needs the IAP tunnel open first: `make vm-tunnel` (see the vm section below).
DATABASE_URL_VM := $(shell grep -E '^DATABASE_URL_VM=' .env 2>/dev/null | head -1 | cut -d= -f2-)

.PHONY: dev serve cloud web web-dev pg migrate help dev-prod cloud-prod migrate-prod _require-prod dev-vm _require-vm vm-tunnel vm-ssh

help:
	@echo "LOCAL (docker Postgres, $(DATABASE_URL)):"
	@echo "  make pg          - run a local Postgres in docker (persistent volume, port 5432)"
	@echo "  make dev         - cloud API + Vite hot-reload dashboard (Ctrl-C stops both)"
	@echo "  make serve       - cloud API serving the prebuilt web/dist, no hot reload"
	@echo "  make cloud       - run only the cloud API   ($(CLOUD_URL))  [needs DATABASE_URL]"
	@echo "  make web         - build the React dashboard into web/dist (served by the API)"
	@echo "  make web-dev     - Vite dev server with hot reload, proxying the API to $(CLOUD_URL)"
	@echo "  make migrate     - apply pending migrations/*.sql to DATABASE_URL (also runs on boot)"
	@echo
	@echo "PROD (DATABASE_URL_PROD from .env):"
	@echo "  make dev-prod    - like 'dev' but against prod Postgres"
	@echo "  make cloud-prod  - like 'cloud' but against prod Postgres"
	@echo "  make migrate-prod- apply migrations to prod Postgres"
	@echo
	@echo "VM (live DB on maat-agent via IAP tunnel, DATABASE_URL_VM from .env):"
	@echo "  make vm-tunnel   - open the IAP tunnel to the VM's Postgres (keep it running)"
	@echo "  make vm-ssh      - ssh into the VM (token: ~/gcontext/.env.selfhost)"
	@echo "  make dev-vm      - like 'dev' but against the VM DB; pass TOKEN=<real token>"
	@echo
	@echo "To connect your AI client in cloud mode, set in its MCP config env:"
	@echo "    GCONTEXT_API_URL=$(CLOUD_URL)   GCONTEXT_TOKEN=$(TOKEN)"

# Local Postgres for dev/tests. Named volume gcontext-pgdata persists data across container
# removal, so it's reusable. `docker rm -f gcontext-pg && docker volume rm gcontext-pgdata`
# for a clean slate.
pg:
	docker run -d --name gcontext-pg -e POSTGRES_PASSWORD=pw -e POSTGRES_DB=gcontext \
		-v gcontext-pgdata:/var/lib/postgresql/data \
		-p 5433:5432 postgres:16

# Hot-reload dev: cloud API in the background + Vite dev server (hot reload) in front,
# Vite proxies API calls to CLOUD_URL. Ctrl-C tears down both (trap on the bg API pid).
# Single \-joined shell line so the trap + bg job share one shell (GNU Make 3.81, no .ONESHELL).
dev:
	@echo ""
	@echo "  >>> OPEN  http://localhost:5179  <<<  (the only URL you open; it proxies the API)"
	@echo ""
	@lsof -ti tcp:5179 -i tcp:$(CLOUD_PORT) | xargs kill -9 2>/dev/null || true
	DATABASE_URL=$(DATABASE_URL) GCONTEXT_DEV_TOKEN=$(TOKEN) PORT=$(CLOUD_PORT) PUBLIC_ORIGIN=http://localhost:5179 uv run cloud_api.py & \
	API_PID=$$!; \
	trap "kill $$API_PID 2>/dev/null; lsof -ti tcp:5179 | xargs kill -9 2>/dev/null" EXIT INT TERM; \
	cd web && npm install && npm run dev

# Run the cloud API serving the prebuilt web/dist (no hot reload). Run `make web` first.
serve:
	DATABASE_URL=$(DATABASE_URL) GCONTEXT_DEV_TOKEN=$(TOKEN) PORT=$(CLOUD_PORT) uv run cloud_api.py

cloud:
	DATABASE_URL=$(DATABASE_URL) GCONTEXT_DEV_TOKEN=$(TOKEN) PORT=$(CLOUD_PORT) uv run cloud_api.py

# Build the React dashboard into web/dist (what cloud_api.py serves at /).
web:
	cd web && npm install && npm run build

# Vite dev server with hot reload. Proxies /rpc,/tokens,/health,/me,/auth to the cloud API,
# so run `make cloud` alongside it. OAuth creds (SESSION_SECRET, GOOGLE_/GITHUB_CLIENT_ID/
# SECRET) go in the backend .env — auth is server-side now, no frontend env needed.
web-dev:
	cd web && npm install && npm run dev

# Apply pending migrations. The server also calls migrate() on boot, so this is just for
# applying a schema change without a full restart (or against a one-off DB).
migrate:
	DATABASE_URL=$(DATABASE_URL) uv run python -c "import cloud_api; cloud_api.migrate()"

# --- prod: same recipes, pointed at DATABASE_URL_PROD from .env ----------------------
# Each just re-invokes the local target with DATABASE_URL overridden (command-line vars beat
# the ?= default; load_dotenv no longer clobbers it). Guard first so an empty prod URL fails
# loudly instead of silently hitting a blank DSN.
_require-prod:
	@test -n "$(DATABASE_URL_PROD)" || { echo "Set DATABASE_URL_PROD=postgres://... in apps/mcp-minimal/.env first"; exit 1; }

dev-prod: _require-prod
	$(MAKE) dev DATABASE_URL='$(DATABASE_URL_PROD)'

# --- vm: dev against the VM's Postgres through the IAP tunnel (port 5439) -------------
# VM = maat-agent (GCP project maat-internal, zone europe-west1-b). Its Postgres listens
# on VM loopback only, so everything goes through the IAP tunnel.
#
# Usage, two terminals:
#   terminal 1:  make vm-tunnel                      (stays open, Ctrl-C to close)
#   terminal 2:  make dev-vm TOKEN=<token>
# then log in to http://localhost:5179 with that same token (workspace 'dev' lives
# behind it — an OAuth login would land in an empty personal workspace).
# The token is on the VM in ~/gcontext/.env.selfhost (GCONTEXT_TOKEN=...); to look:
#   make vm-ssh   then: grep GCONTEXT_TOKEN ~/gcontext/.env.selfhost
vm-tunnel:
	gcloud compute ssh maat-agent --zone europe-west1-b --tunnel-through-iap -- -L 5439:127.0.0.1:5432 -N

vm-ssh:
	gcloud compute ssh maat-agent --zone europe-west1-b --tunnel-through-iap

# TOKEN guard: dev seeds GCONTEXT_DEV_TOKEN into the DB it touches; refuse to plant the
# weak default devtoken into the live VM backend.
_require-vm:
	@test -n "$(DATABASE_URL_VM)" || { echo "Set DATABASE_URL_VM=postgres://... in apps/mcp-minimal/.env first (and open the tunnel, see comment above dev-vm)"; exit 1; }
	@test "$(TOKEN)" != "devtoken" || { echo "Pass TOKEN=<your real GCONTEXT_TOKEN> when targeting the VM DB"; exit 1; }

# Blank the OAuth creds so login_mode()=token: the VM data lives in workspace 'dev',
# reachable only by token login. With .env's OAuth creds active you'd land in your
# personal (empty) OAuth workspace instead. Log in to the dashboard with your TOKEN.
dev-vm: _require-vm
	$(MAKE) dev DATABASE_URL='$(DATABASE_URL_VM)' TOKEN='$(TOKEN)' \
		GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= GITHUB_CLIENT_ID= GITHUB_CLIENT_SECRET=

cloud-prod: _require-prod
	$(MAKE) cloud DATABASE_URL='$(DATABASE_URL_PROD)'

migrate-prod: _require-prod
	$(MAKE) migrate DATABASE_URL='$(DATABASE_URL_PROD)'
