SHELL := /bin/bash
PY ?= .venv/bin/python
SLUG := agent-support-omnicanal
SERVICE := lab-$(SLUG)
# .env n'est pas exporté (les variables de la ligne de commande l'emportent) : les scripts le lisent
# eux-mêmes, le Makefile n'en extrait que ce dont cloud-up a besoin.
lire_env = $(shell sed -n 's/^$(1)=//p' .env 2>/dev/null)
PROJECT ?= $(call lire_env,GOOGLE_CLOUD_PROJECT)
ADMIN_TOKEN ?= $(call lire_env,ADMIN_TOKEN)
WHATSAPP_VERIFY_TOKEN ?= $(or $(call lire_env,WHATSAPP_VERIFY_TOKEN),jeton-de-verification-local)
WHATSAPP_APP_SECRET ?= $(or $(call lire_env,WHATSAPP_APP_SECRET),secret-local-du-simulateur)
REGION ?= europe-west1
# Modèle sur Vertex AI : europe-west1 garde le traitement dans l'UE ; global offre plus de capacité (voir leçon 8).
VERTEX_MODEL ?= gemini-2.5-flash
VERTEX_LOCATION ?= $(REGION)
SA = $(SERVICE)@$(PROJECT).iam.gserviceaccount.com
IMAGES = $(REGION)-docker.pkg.dev/$(PROJECT)/cloud-run-source-deploy/$(SERVICE)
SOURCES = gs://run-sources-$(PROJECT)-$(REGION)/services/$(SERVICE)
COMPOSE = docker compose -p lab-$(SLUG)

.DEFAULT_GOAL := help
help: ## Liste les commandes
	@grep -E '^[a-z0-9-]+:.*## ' $(MAKEFILE_LIST) | awk -F':.*## ' '{printf "  make %-13s %s\n", $$1, $$2}'

setup: ## Crée .venv et installe les dépendances
	@test -d .venv || python3 -m venv .venv
	@.venv/bin/pip install -q -r requirements.txt
	@test -f .env || cp .env.example .env
	@echo "Prêt. Renseignez .env puis : make test"

test: ## Tests sans clé ni réseau (faux modèle)
	@env -u GOOGLE_API_KEY -u GEMINI_API_KEY GOOGLE_GENAI_USE_VERTEXAI=FALSE $(PY) -m pytest -q -p no:warnings

run: ## Lance l'application sur http://localhost:8080
	@$(PY) -m support.app

e2e: ## Scénario réel (web, WhatsApp, escalade, reprise) ; URL=... TOKEN=... pour viser un déploiement
	@$(PY) -W ignore scripts/e2e.py $(if $(URL),--url $(URL) --token $(TOKEN),)

eval: ## Évaluation sur 30 conversations de référence, échoue sous EVAL_SEUIL
	@$(PY) -W ignore eval/run_eval.py

up: ## Démarre l'application dans Docker (port 8080)
	@$(COMPOSE) up -d --build --wait && echo "http://localhost:$${PORT_HOTE:-8080}"

down: ## Arrête la pile Docker et supprime son volume
	@$(COMPOSE) down -v --rmi local 2>/dev/null; echo "Pile Docker arrêtée."

clean: down ## Supprime les artefacts locaux (base, index, rapports, caches)
	@rm -rf var .pytest_cache
	@find . -name __pycache__ -type d -prune -exec rm -rf {} +
	@echo "Artefacts supprimés."

reset: clean ## Retour à l'état initial (garde .env)
	@rm -rf .venv
	@echo "Environnement supprimé (.env conservé)."

cloud-up: ## Déploie sur Cloud Run (Vertex AI, compte de service dédié)
	@test -n "$(PROJECT)" || (echo "Renseignez GOOGLE_CLOUD_PROJECT dans .env"; exit 1)
	@[[ -n "$(ADMIN_TOKEN)" && "$(ADMIN_TOKEN)" != changez-moi* ]] || (echo "Choisissez un ADMIN_TOKEN dans .env (openssl rand -hex 16)"; exit 1)
	gcloud services enable run.googleapis.com cloudbuild.googleapis.com artifactregistry.googleapis.com aiplatform.googleapis.com --project $(PROJECT)
	gcloud iam service-accounts describe $(SA) --project $(PROJECT) >/dev/null 2>&1 || \
	  gcloud iam service-accounts create $(SERVICE) --project $(PROJECT) --display-name "Lab $(SLUG)"
	@# La politique IAM du projet est partagée : en cas de modification concurrente, on réessaie.
	for i in 1 2 3 4; do gcloud projects add-iam-policy-binding $(PROJECT) --member serviceAccount:$(SA) --role roles/aiplatform.user --condition None >/dev/null && break; sleep $$((i*5)); done
	gcloud run deploy $(SERVICE) --source . --project $(PROJECT) --region $(REGION) \
	  --service-account $(SA) --allow-unauthenticated --max-instances 1 --memory 1Gi --timeout 120 \
	  --labels formation-lab=$(SLUG) \
	  --set-env-vars GOOGLE_GENAI_USE_VERTEXAI=TRUE,GOOGLE_CLOUD_PROJECT=$(PROJECT),GOOGLE_CLOUD_LOCATION=$(VERTEX_LOCATION),MODEL=$(VERTEX_MODEL),EMBED_LOCATION=global,ADMIN_TOKEN=$(ADMIN_TOKEN),WHATSAPP_VERIFY_TOKEN=$(WHATSAPP_VERIFY_TOKEN),WHATSAPP_APP_SECRET=$(WHATSAPP_APP_SECRET)
	@echo "URL : $$(gcloud run services describe $(SERVICE) --project $(PROJECT) --region $(REGION) --format 'value(status.url)')"

cloud-status: ## Liste ce qui existe encore pour ce lab
	@echo "Services Cloud Run :"; gcloud run services list --project $(PROJECT) --region $(REGION) --filter "metadata.labels.formation-lab=$(SLUG)" --format "value(metadata.name)"
	@echo "Images :"; gcloud artifacts docker images list $(IMAGES) --project $(PROJECT) --format "value(package)" 2>/dev/null | sort -u
	@echo "Sources téléversées :"; gcloud storage ls "$(SOURCES)/**" --project $(PROJECT) 2>/dev/null || true
	@echo "Compte de service :"; gcloud iam service-accounts list --project $(PROJECT) --filter "email:$(SA)" --format "value(email)"

cloud-down: ## Supprime service, sources, images, droits et compte de service, puis vérifie
	-gcloud run services delete $(SERVICE) --project $(PROJECT) --region $(REGION) --quiet
	-gcloud storage rm -r "$(SOURCES)" --project $(PROJECT) --quiet
	-gcloud artifacts docker images delete $(IMAGES) --project $(PROJECT) --delete-tags --quiet
	-if gcloud iam service-accounts describe $(SA) --project $(PROJECT) >/dev/null 2>&1; then \
	  for i in 1 2 3 4; do gcloud projects remove-iam-policy-binding $(PROJECT) --member serviceAccount:$(SA) --role roles/aiplatform.user --condition None >/dev/null && break; sleep $$((i*5)); done; \
	  gcloud iam service-accounts delete $(SA) --project $(PROJECT) --quiet; fi
	@reste=$$($(MAKE) -s cloud-status | grep -v ':$$'); \
	  if [ -n "$$reste" ]; then echo "Il reste : $$reste"; exit 1; else echo "Plus aucune ressource du lab."; fi

.PHONY: help setup test run e2e eval up down clean reset cloud-up cloud-status cloud-down
