# =============================================================================
# SaveInMed — Makefile
# =============================================================================
# Requisitos:
#   - Go 1.23+  (backend)
#   - pnpm      (frontend e backoffice)  → se preferir npm/yarn, ajuste PKG_MGR
#   - Node 20+  (frontend e backoffice)
#   - Docker + Docker Compose (banco de dados PostgreSQL)
#
# Uso rápido (desenvolvimento diário):
#   make db               → sobe o PostgreSQL via Docker
#   make dev              → sobe backend + frontend em paralelo (hot-reload)
#   make dev-all          → sobe backend + frontend + backoffice em paralelo
#
# Testes (CI/CD e local):
#   make test             → roda TODOS os testes: backend + frontend + backoffice
#   make test-backend     → testes unitários e de integração do Go (go test ./...)
#   make test-frontend    → testes unitários + de componentes (Vitest, modo CI)
#   make test-e2e         → testes end-to-end (Playwright) — exige app rodando
#   make test-ci          → pipeline completo de CI: lint + tests + e2e
#
# Outros:
#   make build            → build de todos os serviços para produção
#   make lint             → lint em todos os serviços
#   make install          → instala dependências de todos os serviços
#   make migrate          → aplica migrações DDL do backend
#   make help             → lista todos os targets com descrições
#
# Variáveis de ambiente para os testes e2e:
#   E2E_BASE_URL    URL do frontend (padrão: http://localhost:5173)
#   E2E_ADMIN_USER  Usuário admin de teste  (padrão: admin)
#   E2E_ADMIN_PASS  Senha admin de teste    (padrão: admin123)
# =============================================================================


# ---------------------------------------------------------------------------
# Variáveis — ajuste aqui se mudar a estrutura de pastas ou gerenciador
# ---------------------------------------------------------------------------

BACKEND_DIR     = backend
FRONTEND_DIR    = frontend
BACKOFFICE_DIR  = backoffice

# Gerenciador de pacotes Node. Troque por "npm" ou "yarn" se necessário.
PKG_MGR         = pnpm

# Caminho do entrypoint Go. Ajuste se o main.go mudar de lugar.
GO_ENTRYPOINT   = ./cmd/api

# Nome e destino do binário compilado do backend.
BINARY_NAME     = api
BINARY_OUT      = $(BACKEND_DIR)/bin/$(BINARY_NAME)

# Flags extras para go build (ex.: -ldflags "-s -w" para reduzir tamanho).
GO_BUILD_FLAGS  =

# Flags extras para go test (ex.: -race -count=1).
GO_TEST_FLAGS   =

# Cores para output (desative com: make COLOR=0 <target>)
COLOR           ?= 1
ifeq ($(COLOR), 1)
  CYAN   = \033[36m
  GREEN  = \033[32m
  YELLOW = \033[33m
  RESET  = \033[0m
else
  CYAN = GREEN = YELLOW = RESET =
endif

# ---------------------------------------------------------------------------
# Targets PHONY — não correspondem a arquivos no disco
# ---------------------------------------------------------------------------
.PHONY: help \
        dev dev-backend dev-frontend dev-backoffice dev-all \
        build build-backend build-frontend build-backoffice \
        test test-backend test-frontend test-backoffice test-e2e test-ci \
        lint lint-backend lint-frontend lint-backoffice \
        migrate prisma-generate \
        install install-frontend install-backoffice install-playwright \
        env clean stop \
        db db-stop db-clean db-logs

# ---------------------------------------------------------------------------
# help — lista os targets e suas descrições
# ---------------------------------------------------------------------------

help:
	@echo ""
	@echo "$(CYAN)SaveInMed — Makefile$(RESET)"
	@echo "════════════════════════════════════════════════════════════"
	@echo "$(YELLOW)Banco de dados$(RESET)"
	@echo "  make db                 Sobe o PostgreSQL via Docker Compose"
	@echo "  make db-stop            Para o container do PostgreSQL"
	@echo "  make db-clean           Remove container + volume (⚠ apaga dados!)"
	@echo "  make db-logs            Exibe logs do PostgreSQL"
	@echo ""
	@echo "$(YELLOW)Desenvolvimento$(RESET)"
	@echo "  make dev                Sobe backend + frontend em paralelo (hot-reload)"
	@echo "  make dev-all            Sobe backend + frontend + backoffice"
	@echo "  make dev-backend        Servidor Go (port 8214)"
	@echo "  make dev-frontend       Vite dev server (port 5173)"
	@echo "  make dev-backoffice     NestJS com ts-node-dev (hot-reload)"
	@echo ""
	@echo "$(YELLOW)Build$(RESET)"
	@echo "  make build              Build completo (Go + Vite + Nest)"
	@echo "  make build-backend      Compila binário Go → $(BINARY_OUT)"
	@echo "  make build-frontend     Vite build de produção → frontend/dist"
	@echo "  make build-backoffice   tsc build Nest → backoffice/dist"
	@echo ""
	@echo "$(YELLOW)Testes$(RESET)"
	@echo "  make test               ★ Roda TODOS os testes (unit + integração)"
	@echo "  make test-backend       go test ./... -cover (Go, com cobertura)"
	@echo "  make test-frontend      Vitest modo CI (sem watch)"
	@echo "  make test-backoffice    Testes do NestJS (quando configurado)"
	@echo "  make test-e2e           Playwright E2E (frontend + backend devem estar rodando)"
	@echo "  make test-ci            Pipeline completo: lint + unit + e2e (usar em CI/CD)"
	@echo "  make install-playwright Instala browsers do Playwright (1ª vez)"
	@echo ""
	@echo "$(YELLOW)Lint$(RESET)"
	@echo "  make lint               Lint em todos os serviços"
	@echo "  make lint-backend       go vet + staticcheck"
	@echo "  make lint-frontend      ESLint via pnpm"
	@echo "  make lint-backoffice    ESLint do NestJS"
	@echo ""
	@echo "$(YELLOW)Infra / Utilitários$(RESET)"
	@echo "  make migrate            Aplica migrações DDL do backend"
	@echo "  make prisma-generate    Gera Prisma Client do backoffice"
	@echo "  make install            Instala dependências de todos os serviços"
	@echo "  make env                Copia .env.example → .env (onde existir)"
	@echo "  make clean              Remove artefatos de build"
	@echo "  make stop               Para processos do make dev"
	@echo "════════════════════════════════════════════════════════════"
	@echo ""
	@echo "$(CYAN)Fluxo de CI/CD recomendado:$(RESET)"
	@echo "  1. make install         → instala dependências"
	@echo "  2. make db              → sobe o banco"
	@echo "  3. make migrate         → aplica migrações"
	@echo "  4. make lint            → verifica qualidade do código"
	@echo "  5. make test            → testes unitários e de integração"
	@echo "  6. make dev-backend &   → sobe o backend"
	@echo "     make test-e2e        → testes end-to-end"
	@echo ""


# =============================================================================
# BANCO DE DADOS (Docker)
# =============================================================================

# Inicia o container PostgreSQL em background.
db:
	@echo "$(GREEN)▶ Iniciando PostgreSQL (Docker)...$(RESET)"
	docker compose up -d db
	@echo "$(GREEN)✔ Aguardando o banco ficar pronto...$(RESET)"
	@docker compose exec db sh -c 'until pg_isready -U postgres -d saveinmed; do sleep 1; done'
	@echo "$(GREEN)✔ PostgreSQL pronto na porta 55432$(RESET)"

# Para e remove o container (dados persistem no volume).
db-stop:
	@echo "$(YELLOW)▶ Parando PostgreSQL...$(RESET)"
	docker compose stop db

# Remove o container e o volume (dados perdidos!).
db-clean:
	@echo "$(YELLOW)▶ Removendo container e volume do PostgreSQL...$(RESET)"
	docker compose down -v

# Exibe os logs do container do banco.
db-logs:
	docker compose logs -f db


# =============================================================================
# DESENVOLVIMENTO
# =============================================================================

# Sobe backend e frontend em paralelo — ideal para o dia a dia.
# O & em cada comando faz rodar em background; o wait aguarda ambos.
dev:
	@echo "$(GREEN)▶ Subindo backend e frontend...$(RESET)"
	@$(MAKE) dev-backend & \
	$(MAKE) dev-frontend & \
	wait

# Sobe os três serviços em paralelo.
dev-all:
	@echo "$(GREEN)▶ Subindo backend, frontend e backoffice...$(RESET)"
	@$(MAKE) dev-backend   & \
	$(MAKE) dev-frontend   & \
	$(MAKE) dev-backoffice & \
	wait

# Roda o servidor Go. Não tem hot-reload nativo; use 'air' se quiser:
#   go install github.com/cosmtrek/air@latest  →  cd backend && air
dev-backend:
	@echo "$(GREEN)▶ Backend Go ($(BACKEND_DIR))$(RESET)"
	cd $(BACKEND_DIR) && go run $(GO_ENTRYPOINT)

# Roda o Vite dev server com HMR.
dev-frontend:
	@echo "$(GREEN)▶ Frontend Vite ($(FRONTEND_DIR))$(RESET)"
	cd $(FRONTEND_DIR) && $(PKG_MGR) dev

# Roda o NestJS com ts-node-dev (hot-reload automático em src/).
dev-backoffice:
	@echo "$(GREEN)▶ Backoffice NestJS ($(BACKOFFICE_DIR))$(RESET)"
	cd $(BACKOFFICE_DIR) && $(PKG_MGR) start:dev


# =============================================================================
# BUILD
# =============================================================================

# Compila todos os serviços.
build: build-backend build-frontend build-backoffice
	@echo "$(GREEN)✔ Build completo concluído.$(RESET)"

# Compila o binário Go. O resultado fica em backend/bin/api.
# Ajuste GO_BUILD_FLAGS acima para adicionar -ldflags, -tags, etc.
build-backend:
	@echo "$(GREEN)▶ Build backend Go → $(BINARY_OUT)$(RESET)"
	mkdir -p $(BACKEND_DIR)/bin
	cd $(BACKEND_DIR) && go build $(GO_BUILD_FLAGS) -o bin/$(BINARY_NAME) $(GO_ENTRYPOINT)

# Build de produção do React/Vite. Artefatos em frontend/dist/.
build-frontend:
	@echo "$(GREEN)▶ Build frontend Vite$(RESET)"
	cd $(FRONTEND_DIR) && $(PKG_MGR) build

# Build de produção do NestJS. Artefatos em backoffice/dist/.
build-backoffice:
	@echo "$(GREEN)▶ Build backoffice NestJS$(RESET)"
	cd $(BACKOFFICE_DIR) && $(PKG_MGR) build


# =============================================================================
# TESTES
# =============================================================================
#
# Estrutura de testes do projeto:
#
#   Backend (Go):
#     - Testes de unidade: internal/usecase/*_test.go
#         Cobrem: auth, shipping, orders, financials, cart, products
#     - Testes de contrato: internal/http/handler/contract_test.go
#         Documentam e verificam divergências frontend ↔ backend
#     - Testes de handler: internal/http/handler/handler_test.go
#         Cobrem todos os endpoints HTTP com mocks em memória
#
#   Frontend (TypeScript/Vitest):
#     - Testes de serviço: src/services/*.test.ts
#         Cobrem chamadas de API e mapeamento de respostas
#     - Testes de componente: src/components/*.test.tsx
#         Cobrem renderização e interação de UI
#     - Testes de contexto: src/context/*.test.tsx
#         Cobrem AuthContext, ThemeContext
#     - Testes de integração: src/tests/integration/apiContracts.test.ts
#         Documentam divergências de contrato
#
#   E2E (Playwright):
#     - e2e/login.spec.ts      → fluxo de autenticação
#     - e2e/marketplace.spec.ts → marketplace e busca
#     - e2e/checkout.spec.ts   → checkout e pedidos
#
# =============================================================================

# Roda TODOS os testes de unidade + integração (sem e2e).
# Use este target em PRs e na maioria dos cenários de CI.
test: test-backend test-frontend test-backoffice
	@echo "$(GREEN)✔ Todos os testes de unidade e integração concluídos.$(RESET)"
	@echo "  Para testes E2E, execute: make test-e2e"

# ─────────────────────────────────────────────
# Backend — Go
# ─────────────────────────────────────────────

# Executa todos os testes Go com relatório de cobertura.
# Inclui: testes de unidade (usecase), testes de contrato (handler/contract_test.go)
# e testes de handler (handler_test.go).
#
# Para detectar data races (recomendado em CI):
#   make test-backend GO_TEST_FLAGS=-race
#
# Para ver cobertura em HTML:
#   cd backend && go test ./... -coverprofile=coverage.out && go tool cover -html=coverage.out
test-backend:
	@echo "$(GREEN)▶ Testes Go (backend)$(RESET)"
	cd $(BACKEND_DIR) && go test $(GO_TEST_FLAGS) ./... -cover

# ─────────────────────────────────────────────
# Frontend — Vitest (modo CI, sem watch)
# ─────────────────────────────────────────────

# Executa todos os testes Vitest uma vez e encerra (modo CI).
# Inclui: unit tests de serviços, componentes, contextos e integração.
#
# Para ver cobertura HTML:
#   make test-frontend-coverage
#
# Para modo watch (desenvolvimento):
#   cd frontend && pnpm test
test-frontend:
	@echo "$(GREEN)▶ Testes frontend (Vitest — modo CI)$(RESET)"
	cd $(FRONTEND_DIR) && $(PKG_MGR) run test:run

# Testes frontend com relatório de cobertura (HTML + texto).
test-frontend-coverage:
	@echo "$(GREEN)▶ Cobertura de testes frontend$(RESET)"
	cd $(FRONTEND_DIR) && $(PKG_MGR) run test:coverage

# ─────────────────────────────────────────────
# Backoffice — NestJS
# ─────────────────────────────────────────────

# Testes do NestJS. Adicione "test": "jest" no backoffice/package.json
# quando configurar o Jest. Por ora exibe instruções.
#
# Para ativar:
#   1. Instale Jest no backoffice: cd backoffice && pnpm add -D jest @types/jest ts-jest
#   2. Adicione "test": "jest" no backoffice/package.json
#   3. Remova o echo abaixo e descomente a linha do pnpm
test-backoffice:
	@echo "$(YELLOW)⚠  Testes do backoffice NestJS: ainda não configurados.$(RESET)"
	@echo "   Para ativar, adicione 'test': 'jest' no backoffice/package.json."
	@echo "   Então substitua este target por:"
	@echo "     cd $(BACKOFFICE_DIR) && $(PKG_MGR) test"

# ─────────────────────────────────────────────
# E2E — Playwright
# ─────────────────────────────────────────────

# Executa os testes end-to-end com Playwright.
#
# PRÉ-REQUISITO: frontend e backend devem estar rodando antes de executar este target.
# O playwright.config.ts está configurado para subir o frontend automaticamente
# via webServer, mas o backend precisa estar rodando manualmente:
#
#   Opção 1 — Manual:
#     Terminal 1: make dev-backend
#     Terminal 2: make test-e2e
#
#   Opção 2 — Automático com make:
#     make test-e2e-full  (sobe backend, roda e2e, derruba backend)
#
# Variáveis de ambiente úteis:
#   E2E_BASE_URL=http://localhost:5173  (URL do frontend)
#   E2E_ADMIN_USER=admin               (usuário admin para testes)
#   E2E_ADMIN_PASS=admin123            (senha admin para testes)
#
# Para instalar os browsers na primeira vez: make install-playwright
test-e2e:
	@echo "$(GREEN)▶ Testes E2E (Playwright)$(RESET)"
	@echo "  ℹ️  Certifique-se de que o backend está rodando em localhost:8214"
	cd $(FRONTEND_DIR) && $(PKG_MGR) e2e

# Variante interativa — abre o Playwright UI para debug visual.
test-e2e-ui:
	@echo "$(GREEN)▶ Playwright UI (debug interativo)$(RESET)"
	cd $(FRONTEND_DIR) && $(PKG_MGR) e2e:ui

# Sobe o backend em background, roda os testes E2E, derruba o backend.
# Útil em CI quando o backend precisa ser iniciado automaticamente.
#
# Nota: o frontend é gerenciado pelo playwright.config.ts (webServer).
test-e2e-full:
	@echo "$(GREEN)▶ E2E completo: sobe backend → roda e2e → derruba backend$(RESET)"
	cd $(BACKEND_DIR) && go run $(GO_ENTRYPOINT) & \
	BACKEND_PID=$$!; \
	sleep 3; \
	cd $(FRONTEND_DIR) && $(PKG_MGR) e2e; \
	E2E_STATUS=$$?; \
	kill $$BACKEND_PID 2>/dev/null || true; \
	exit $$E2E_STATUS

# Instala os browsers do Playwright (necessário apenas na primeira vez).
# Execute este comando antes de rodar os testes E2E em uma nova máquina ou CI.
install-playwright:
	@echo "$(GREEN)▶ Instalando browsers do Playwright$(RESET)"
	cd $(FRONTEND_DIR) && $(PKG_MGR) exec playwright install --with-deps

# ─────────────────────────────────────────────
# Pipeline completo de CI/CD
# ─────────────────────────────────────────────

# Pipeline completo: lint + testes de unidade + testes E2E.
# Use este target no CI/CD (GitHub Actions, GitLab CI, etc.):
#
#   jobs:
#     test:
#       steps:
#         - run: make install
#         - run: make db
#         - run: make migrate
#         - run: make test-ci
#
# Para rodar só os testes de unidade sem E2E (mais rápido em PRs):
#   make test
test-ci: lint test test-e2e-full
	@echo "$(GREEN)✔ Pipeline de CI completo: lint + unit tests + e2e — PASSOU.$(RESET)"


# =============================================================================
# LINT
# =============================================================================

# Lint em todos os serviços.
lint: lint-backend lint-frontend lint-backoffice

# go vet + staticcheck (se instalado). Para instalar staticcheck:
#   go install honnef.co/go/tools/cmd/staticcheck@latest
lint-backend:
	@echo "$(GREEN)▶ Lint backend Go$(RESET)"
	cd $(BACKEND_DIR) && go vet ./...
	@which staticcheck > /dev/null 2>&1 && \
		(cd $(BACKEND_DIR) && staticcheck ./...) || \
		echo "$(YELLOW)  staticcheck não instalado — pulando análise estática$(RESET)"

# ESLint do frontend (se houver script lint configurado no package.json).
lint-frontend:
	@echo "$(GREEN)▶ Lint frontend$(RESET)"
	cd $(FRONTEND_DIR) && $(PKG_MGR) run lint 2>/dev/null || \
		echo "$(YELLOW)  Script 'lint' não encontrado em $(FRONTEND_DIR)/package.json$(RESET)"

# ESLint do NestJS — usa eslint configurado no backoffice.
lint-backoffice:
	@echo "$(GREEN)▶ Lint backoffice NestJS$(RESET)"
	cd $(BACKOFFICE_DIR) && $(PKG_MGR) run lint


# =============================================================================
# INFRA / UTILITÁRIOS
# =============================================================================

# Aplica as migrações DDL do backend Go.
migrate:
	@echo "$(GREEN)▶ Aplicando migrações Do backend$(RESET)"
	cd $(BACKEND_DIR) && go run ./cmd/apply_migration

# Regenera o Prisma Client do backoffice após alterações no schema.prisma.
prisma-generate:
	@echo "$(GREEN)▶ Gerando Prisma Client$(RESET)"
	cd $(BACKOFFICE_DIR) && $(PKG_MGR) run prisma:generate

# Instala dependências de todos os serviços.
# As dependências Go são gerenciadas pelo go.mod (go mod download automático).
# O Playwright precisa de uma etapa adicional (make install-playwright) para
# baixar os browsers binários — necessário apenas na primeira vez.
install: install-frontend install-backoffice
	@echo "$(GREEN)▶ Baixando módulos Go$(RESET)"
	cd $(BACKEND_DIR) && go mod download
	@echo "$(GREEN)✔ Todas as dependências instaladas.$(RESET)"
	@echo "$(YELLOW)  Dica: execute 'make install-playwright' para instalar os browsers do Playwright$(RESET)"
	@echo "$(YELLOW)  (necessário apenas na primeira vez ou em CI)$(RESET)"

install-frontend:
	@echo "$(GREEN)▶ Instalando dependências do frontend$(RESET)"
	cd $(FRONTEND_DIR) && $(PKG_MGR) install

install-backoffice:
	@echo "$(GREEN)▶ Instalando dependências do backoffice$(RESET)"
	cd $(BACKOFFICE_DIR) && $(PKG_MGR) install

# Copia arquivos .env.example → .env para cada serviço (sem sobrescrever).
# Crie os .env.example em cada pasta para ativar este target.
env:
	@for dir in $(BACKEND_DIR) $(FRONTEND_DIR) $(BACKOFFICE_DIR); do \
		if [ -f "$$dir/.env.example" ] && [ ! -f "$$dir/.env" ]; then \
			cp "$$dir/.env.example" "$$dir/.env"; \
			echo "$(GREEN)  ✔ $$dir/.env criado a partir de .env.example$(RESET)"; \
		elif [ -f "$$dir/.env.example" ]; then \
			echo "$(YELLOW)  ⚠  $$dir/.env já existe — não sobrescrito$(RESET)"; \
		else \
			echo "$(YELLOW)  –  $$dir/.env.example não encontrado — pulando$(RESET)"; \
		fi \
	done

# Remove todos os artefatos de build.
clean:
	@echo "$(GREEN)▶ Limpando artefatos...$(RESET)"
	rm -rf $(BACKEND_DIR)/bin
	rm -rf $(FRONTEND_DIR)/dist
	rm -rf $(BACKOFFICE_DIR)/dist
	@echo "$(GREEN)✔ Artefatos removidos.$(RESET)"

# Para processos do make dev (salva PIDs em .dev.pids).
# Uso: make dev-bg para subir em background gravando PIDs,
#      make stop para matar os processos.
#
# Nota: 'make dev' usa wait/& diretamente, então Ctrl+C já encerra tudo.
# Este target é útil se você subir os serviços manualmente em background.
stop:
	@if [ -f .dev.pids ]; then \
		echo "$(GREEN)▶ Parando processos...$(RESET)"; \
		xargs kill < .dev.pids 2>/dev/null || true; \
		rm -f .dev.pids; \
		echo "$(GREEN)✔ Processos encerrados.$(RESET)"; \
	else \
		echo "$(YELLOW)  Nenhum arquivo .dev.pids encontrado.$(RESET)"; \
		echo "  Use Ctrl+C para parar 'make dev', ou mate os processos manualmente."; \
	fi
