# ==============================================================================
# Makefile — Sposato (PHP 8.5 + Laravel 12 + PostgreSQL 18 + proxy)
#
# Interface operacional única (guideline 11). Rode `make` ou `make help`.
# ==============================================================================

COMPOSE     ?= docker compose
DC          = $(COMPOSE)
SERVICE     ?= laravel
DB_SERVICE  ?= db
DB_USER     ?= postgres
LEGACY_DB   ?= marketplace
NOVO_DB     ?= marketplace_laravel
TEST_DB     ?= marketplace_test
APP_PORT    ?= 8000
BASE_URL    ?= http://localhost:$(APP_PORT)
PROD_ENV    ?= .env.prod
PROD         = docker compose --env-file $(PROD_ENV) -f docker-compose.prod.yml
E2E_DIR     ?= e2e

# Ambiente determinístico dos testes: fila/cache/sessão em memória e e-mail
# capturado, independente do .env do container.
ENV_TESTE   = -e QUEUE_CONNECTION=sync -e CACHE_STORE=array \
              -e SESSION_DRIVER=array -e MAIL_MAILER=array -e LOG_LEVEL=warning

.DEFAULT_GOAL := help
.PHONY: help up down build logs shell db-shell migrate seed db-test schema-parity \
        test test-parallel analyse lint lint-fix e2e contract sniffcss proxy-reload \
        assets env certs prod-config prod-pull prod-build prod-up prod-migrate prod-seed \
        prod-health prod-deploy prod-logs prod-down

# ------------------------------------------------------------------ ajuda
help: ## Mostra esta ajuda
	@grep -hE '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
		| awk 'BEGIN {FS = ":.*?## "}; {printf "  \033[36m%-16s\033[0m %s\n", $$1, $$2}'

# ------------------------------------------------------------------ ciclo principal
up: certs env ## Sobe a stack, aplica migrations e seed
	$(DC) up -d --build
	@until $(DC) exec -T $(DB_SERVICE) pg_isready -U $(DB_USER) -d $(LEGACY_DB) >/dev/null 2>&1; do sleep 1; done
	@$(MAKE) --no-print-directory migrate
	@$(MAKE) --no-print-directory seed
	@echo ""
	@echo "✅ Stack no ar em $(BASE_URL)"

# ------------------------------------------------------------------ produção
# Produção usa apenas imagens publicadas (ADR-0012). `.env.prod` fica fora do
# git e traz as variáveis do compose de produção (ver .env.prod.example).
prod-config: ## Valida o compose de produção (exige .env.prod)
	@test -f $(PROD_ENV) || { echo "❌ $(PROD_ENV) ausente; use .env.prod.example como base."; exit 1; }
	$(PROD) config > /dev/null && echo "✅ compose de produção válido"

prod-pull: ## Baixa as imagens publicadas no registry
	$(PROD) pull

prod-up: ## Sobe a stack de produção com as imagens do registry
	$(PROD) up -d --wait

prod-build: ## Builda as duas imagens com as tags de .env.prod (homolog sem registry)
	@set -a; . ./$(PROD_ENV); set +a; \
	  docker build -t "$$SPOSATO_IMAGE" -f docker/php/Dockerfile . && \
	  docker build --target web -t "$$SPOSATO_WEB_IMAGE" -f docker/php/Dockerfile .

prod-migrate: ## Roda as migrations na stack de produção
	$(PROD) run --rm laravel php artisan migrate --force

prod-seed: ## Popula o banco (somente homologação)
	$(PROD) run --rm laravel php artisan db:seed --force

prod-health: ## Valida /up na stack de produção
	@set -a; . ./$(PROD_ENV); set +a; \
	  curl -fsS "http://127.0.0.1:$${APP_PORT:-8000}/up" > /dev/null && echo "✅ health ok"

prod-deploy: ## Deploy: pull + up + migrations + health check
	$(PROD) pull
	$(PROD) up -d --wait
	@$(MAKE) --no-print-directory prod-migrate
	@$(MAKE) --no-print-directory prod-health

prod-logs: ## Acompanha os logs da stack de produção
	$(PROD) logs -f --tail=200 laravel laravel-queue laravel-web proxy

prod-down: ## Para a stack de produção (mantém volumes)
	$(PROD) down --remove-orphans

down: ## Para os containers (mantém volumes e dados)
	$(DC) down --remove-orphans

build: ## Builda as imagens do Laravel
	$(DC) build laravel

logs: ## Acompanha os logs da aplicação, worker e proxy
	$(DC) logs -f --tail=200 laravel laravel-queue laravel-web proxy

shell: ## Shell no container do Laravel
	$(DC) exec $(SERVICE) sh

db-shell: ## psql no banco
	$(DC) exec $(DB_SERVICE) psql -U $(DB_USER) -d $(LEGACY_DB)

certs: ## Gera a CA/certificado TLS de desenvolvimento (se faltarem)
	@scripts/gerar-certs-dev.sh

env: ## Garante um .env com projeto/portas (usa .env.example se faltar)
	@test -f .env || { cp .env.example .env; echo "📝 .env criado a partir de .env.example (defina LARAVEL_APP_KEY)."; }

assets: ## Compila CSS/JS com Vite (imagem node, sem depender do host)
	docker run --rm -v "$(CURDIR)":/app -w /app node:22-alpine sh -c 'npm ci --no-audit --no-fund && npm run build'

# ------------------------------------------------------------------ banco
migrate: ## Aplica as migrations (baseline + aditivas)
	$(DC) exec -T $(SERVICE) php artisan migrate --force

seed: ## Popula o banco com o seed determinístico
	$(DC) exec -T $(SERVICE) php artisan db:seed --force

db-test: ## (Re)cria o banco de teste e aplica as migrations
	$(DC) exec -T $(DB_SERVICE) psql -U $(DB_USER) -d postgres \
		-c "drop database if exists $(NOVO_DB);" -c "create database $(NOVO_DB);"
	$(DC) exec -T $(SERVICE) sh -c 'DB_DATABASE=$(NOVO_DB) php artisan migrate --force'

schema-parity: ## Compara o schema com o criado pela baseline (diff zero)
	$(DC) exec -T $(DB_SERVICE) env LEGACY_DB=$(LEGACY_DB) NOVO_DB=$(NOVO_DB) sh /scripts/schema-parity.sh

# ------------------------------------------------------------------ qualidade
test: ## Roda a suíte PHPUnit no PostgreSQL real
	$(DC) exec -T -e DB_DATABASE=$(TEST_DB) $(ENV_TESTE) $(SERVICE) php artisan test

test-parallel: ## Roda a suíte com ParaTest
	$(DC) exec -T -e DB_DATABASE=$(TEST_DB) $(ENV_TESTE) $(SERVICE) php artisan test --parallel

analyse: ## PHPStan/Larastan nível máximo
	$(DC) exec -T $(SERVICE) composer analyse

lint: ## Pint em modo verificação
	$(DC) exec -T $(SERVICE) composer lint

lint-fix: ## Pint corrigindo o estilo
	$(DC) exec -T $(SERVICE) composer lint:fix

# ------------------------------------------------------------------ E2E / contrato
e2e: ## Playwright contra o proxy (E2E_BASE_URL=$(BASE_URL))
	@test -d $(E2E_DIR)/node_modules || (cd $(E2E_DIR) && npm ci)
	cd $(E2E_DIR) && E2E_BASE_URL=$(BASE_URL) npx playwright test

contract: ## Contrato da API v1 (OpenAPI versionado + envelope)
	$(DC) run --rm contract node api-contract.mjs

sniffcss: ## Captura a baseline de estilos computados (SniffCSS)
	@test -n "$(SNIFF_URL)" || { echo "uso: make sniffcss SNIFF_URL=$(BASE_URL)/servicos"; exit 1; }
	npx --yes sniffcss --url "$(SNIFF_URL)" --selector 'body' \
		--depth 8 --viewport 1366x768 --output json --pretty --stabilize --contrast --ax \
		> $(SNIFF_OUT:-/tmp/sniff.json)

# ------------------------------------------------------------------ proxy
proxy-reload: ## Valida a config do nginx e recarrega o proxy
	$(DC) exec -T proxy nginx -t
	$(DC) exec -T proxy nginx -s reload
