.DEFAULT_GOAL := help

# Permet d'utiliser un .env.docker.local pour override
ENV_DEFAULT = infra/dev/.env.docker
ENV_LOCAL   = infra/dev/.env.docker.local
ENV_FILE    := $(if $(wildcard $(ENV_LOCAL)),$(ENV_LOCAL),$(ENV_DEFAULT))

# Permet d'avoir les variables du fichier .env.docker.local
include $(ENV_DEFAULT)
-include $(ENV_LOCAL)

# Export du UID/GID host pour que docker compose les voie dans toutes les targets
# (sinon le build du Dockerfile dev fail sur `usermod -u ${CURRENT_UID}` quand l'image
# n'est pas en cache, ex: apres renommage du compose project).
export CURRENT_UID := $(shell id -u)
export CURRENT_GID := $(shell id -g)

PHP_CONTAINER				= php-$(DOCKER_APP_NAME)-fpm
SYMFONY_CONSOLE				= $(EXEC_PHP) php bin/console

DOCKER_COMPOSE = docker compose --env-file $(ENV_FILE)
DOCKER						= docker

EXEC_PHP					= $(DOCKER) exec -t -u $(APP_USER) $(PHP_CONTAINER)
EXEC_PHP_CS_FIXER			= $(EXEC_PHP) php vendor/bin/php-cs-fixer
EXEC_PHP_ROOT				= $(DOCKER) exec -t -u root $(PHP_CONTAINER)
EXEC_PHP_INTERACTIVE		= $(DOCKER) exec -it -u $(APP_USER) $(PHP_CONTAINER)
EXEC_PHP_INTERACTIVE_ROOT	= $(DOCKER) exec -it -u root $(PHP_CONTAINER)
FILES						=

#========================================================================================

# Affiche l'aide — cible par defaut (make ou make help)
help:
	@printf "\n  \033[1mStarseed — Commandes make\033[0m\n\n"
	@printf "  \033[1;33mContainers\033[0m\n"
	@printf "    \033[36m%-28s\033[0m %s\n" "start"                    "Demarrer les containers Docker"
	@printf "    \033[36m%-28s\033[0m %s\n" "stop"                     "Arreter les containers"
	@printf "    \033[36m%-28s\033[0m %s\n" "restart"                  "Redemarrer les containers"
	@printf "    \033[36m%-28s\033[0m %s\n" "shell"                    "Shell bash dans le container PHP (user app)"
	@printf "    \033[36m%-28s\033[0m %s\n" "shell-root"               "Shell bash dans le container PHP (root)"
	@printf "    \033[36m%-28s\033[0m %s\n" "logs-dev"                 "Tail des logs Symfony (var/log/dev.log)"
	@printf "\n  \033[1;33mInstallation\033[0m\n"
	@printf "    \033[36m%-28s\033[0m %s\n" "install"                  "Install complet (composer, migrations, fixtures, build Nuxt)"
	@printf "    \033[36m%-28s\033[0m %s\n" "reset"                    "Tout supprimer et reinstaller (ATTENTION : drop la BDD)"
	@printf "    \033[36m%-28s\033[0m %s\n" "composer-install"         "Composer install + generation cles JWT"
	@printf "    \033[36m%-28s\033[0m %s\n" "build-nuxtJS"             "npm install + build Nuxt (prod)"
	@printf "    \033[36m%-28s\033[0m %s\n" "build-without-cache"      "Rebuild des images Docker sans cache"
	@printf "    \033[36m%-28s\033[0m %s\n" "copy-git-hook"            "Copie les hooks git (pre-commit, commit-msg)"
	@printf "    \033[36m%-28s\033[0m %s\n" "node-use"                 "Force la version Node via nvm"
	@printf "\n  \033[1;33mFrontend (Nuxt)\033[0m\n"
	@printf "    \033[36m%-28s\033[0m %s\n" "dev-nuxt"                 "Serveur dev Nuxt avec hot reload (port 3004)"
	@printf "    \033[36m%-28s\033[0m %s\n" "nuxt-lint"                "Lint TypeScript/Vue"
	@printf "    \033[36m%-28s\033[0m %s\n" "nuxt-lint-fix"            "Lint + auto-fix"
	@printf "\n  \033[1;33mBase de donnees\033[0m\n"
	@printf "    \033[36m%-28s\033[0m %s\n" "migration-migrate"        "Lancer les migrations Doctrine"
	@printf "    \033[36m%-28s\033[0m %s\n" "fixtures"                 "Charger les fixtures"
	@printf "    \033[36m%-28s\033[0m %s\n" "sync-permissions"         "Synchroniser le catalogue RBAC"
	@printf "    \033[36m%-28s\033[0m %s\n" "db-reset"                 "Reset BDD (drop + migrate + fixtures + perms)"
	@printf "    \033[36m%-28s\033[0m %s\n" "db-restart"               "Restart du container BDD"
	@printf "    \033[36m%-28s\033[0m %s\n" "test-db-setup"            "Cree et initialise la BDD de test"
	@printf "    \033[36m%-28s\033[0m %s\n" "cache-clear"              "Vider le cache Symfony"
	@printf "\n  \033[1;33mTests\033[0m\n"
	@printf "    \033[36m%-28s\033[0m %s\n" "test"                     "PHPUnit (tests back)"
	@printf "    \033[36m%-28s\033[0m %s\n" "nuxt-test"                "Vitest (tests unitaires front)"
	@printf "    \033[36m%-28s\033[0m %s\n" "test-all"                 "PHPUnit + Vitest"
	@printf "    \033[36m%-28s\033[0m %s\n" "test-e2e"                 "Playwright (tests E2E front)"
	@printf "    \033[36m%-28s\033[0m %s\n" "test-e2e-ui"              "Playwright UI interactive (debug)"
	@printf "    \033[36m%-28s\033[0m %s\n" "seed-e2e"                 "Seed les 6 personas E2E"
	@printf "    \033[36m%-28s\033[0m %s\n" "install-e2e-deps"         "One-time : Chromium + libs systeme (sudo)"
	@printf "\n  \033[1;33mQualite code\033[0m\n"
	@printf "    \033[36m%-28s\033[0m %s\n" "php-cs-fixer-allow-risky" "Fix code style PHP (utilise par le pre-commit)"
	@printf "    \033[36m%-28s\033[0m %s\n" "php-cs-fixer-check"       "Dry-run du fixer (CI / verif avant push)"
	@printf "\n  Plus de details : \033[4mREADME.md\033[0m, \033[4mCLAUDE.md\033[0m\n\n"

env-init:
	@cp --update=none $(ENV_DEFAULT) $(ENV_LOCAL)

# Lance le container
start: env-init
	@echo "**** START CONTAINERS ****"
	CURRENT_UID=$(shell id -u) CURRENT_GID=$(shell id -g) $(DOCKER_COMPOSE) up -d

# Éteint le container
stop:
	$(DOCKER_COMPOSE) stop

restart: env-init
	$(DOCKER_COMPOSE) down
	CURRENT_UID=$(shell id -u) CURRENT_GID=$(shell id -g) $(DOCKER_COMPOSE) up -d

install: copy-git-hook composer-install cache-clear node-use build-nuxtJS migration-migrate sync-permissions test-db-setup

# Supprime tout est réinstalle tout (Attention ça supprime la bdd aussi)
reset: delete_built_dir remove_orphans build-without-cache start wait install

composer-install:
	$(EXEC_PHP_ROOT) mkdir -p /var/www/html/var/cache /var/www/html/var/log
	$(EXEC_PHP_ROOT) chown -R www-data:www-data /var/www/html/var
	$(EXEC_PHP) composer install
	$(SYMFONY_CONSOLE) lexik:jwt:generate-keypair --skip-if-exists

build-nuxtJS:
	$(EXEC_PHP_ROOT) chown -R $(APP_USER):$(APP_USER) /var/www/html/frontend
	$(EXEC_PHP) sh -lc "cd frontend && npm install && npm run build:dist"

dev-nuxt:
	$(EXEC_PHP) sh -c "cd frontend && npm run dev"

nuxt-lint:
	$(EXEC_PHP) sh -c "cd frontend && npm run lint"

nuxt-lint-fix:
	$(EXEC_PHP) sh -c "cd frontend && npm run lint:fix"

# Lance les tests unitaires frontend (Vitest)
nuxt-test:
	$(EXEC_PHP) sh -c "cd frontend && npm run test"

# Seed les 6 personas E2E (idempotent). A relancer des que le catalogue
# permissions bouge (sync-permissions) ou avant chaque run test-e2e.
seed-e2e:
	$(SYMFONY_CONSOLE) app:seed-e2e

# Bootstrap one-time pour les tests E2E sur un nouveau poste :
#   1. Telecharge Chromium dans ~/.cache/ms-playwright
#   2. Installe les deps systeme (libnss3, libasound, libatk, etc.) :
#      - Ubuntu/Debian : `playwright install-deps` (officiel)
#      - Fedora/RHEL   : liste dnf equivalente (playwright ne gere pas dnf)
#      - Autre         : avertissement, a faire a la main.
#
# Le `sudo env "PATH=$$PATH"` est necessaire car avec NVM, `sudo npx` ne
# trouve pas npx (le PATH de sudo est vide par defaut). On preserve
# explicitement le PATH courant pour que npx resolve.
#
# A relancer uniquement si tu upgrade @playwright/test (les deps peuvent
# bouger entre versions majeures).
install-e2e-deps:
	cd frontend && npx playwright install chromium
	@if command -v apt-get >/dev/null 2>&1; then \
		echo ">> Detected apt-get — using playwright install-deps"; \
		cd frontend && sudo env "PATH=$$PATH" npx playwright install-deps chromium; \
	elif command -v dnf >/dev/null 2>&1; then \
		echo ">> Detected dnf — installing Chromium deps via dnf"; \
		sudo dnf install -y \
			nss nspr dbus-libs atk at-spi2-atk at-spi2-core cups-libs \
			libdrm libX11 libXcomposite libXdamage libXfixes libXrandr \
			libXext libXtst libxkbcommon mesa-libgbm alsa-lib \
			pango cairo libwayland-client; \
	else \
		echo ">> No supported package manager detected (apt-get / dnf)."; \
		echo ">> Install Chromium system libs manually, then re-run test-e2e."; \
		exit 1; \
	fi

# Lance les tests E2E Playwright sur l'host. Pre-requis :
#   - `make install-e2e-deps` (une fois par poste)
#   - `make start` (containers en vie)
#   - `make dev-nuxt` dans un autre terminal (serve frontend sur :3004)
#   - `make seed-e2e` (personas crees)
test-e2e:
	cd frontend && npm run test:e2e

# UI interactive Playwright (debug facile)
test-e2e-ui:
	cd frontend && npm run test:e2e:ui

delete_built_dir:
	CURRENT_UID=$(shell id -u) CURRENT_GID=$(shell id -g) $(DOCKER_COMPOSE) up -d
	$(DOCKER) exec -u root $(PHP_CONTAINER) rm -rf vendor/
	$(DOCKER) exec -u root $(PHP_CONTAINER) rm -rf frontend/node_modules

remove_orphans:
	$(DOCKER_COMPOSE) kill
	$(DOCKER_COMPOSE) down --volumes --remove-orphans

build-without-cache:
	$(DOCKER_COMPOSE) build	\
		--build-arg="DOCKER_PHP_VERSION=$(DOCKER_PHP_VERSION)" 	\
		--build-arg="DOCKER_NODE_VERSION=$(DOCKER_NODE_VERSION)" 	\
		--build-arg="CURRENT_UID=$(shell id -u)" 	\
		--build-arg="CURRENT_GID=$(shell id -g)" 	\
 		--no-cache

migration-migrate:
	$(SYMFONY_CONSOLE) doctrine:migrations:migrate --no-interaction

# Cree et initialise la base de test utilisee par PHPUnit
# (le suffixe "_test" est applique automatiquement par Doctrine en APP_ENV=test)
#
# Ordre :
#  1. migrations : crees le schema metier reel.
#  2. schema:update : cree les tables mappees en `when@test` uniquement
#     (ex: fake_site_aware_entity du ticket 4) qui n'ont pas de migration.
#     `--force` sans `--complete` : ajoute les tables manquantes aux
#     mappings sans drop les tables DB non mappees (no-op sur un schema
#     deja aligne avec les migrations). Necessaire car le purger
#     doctrine:fixtures:load essaie de DELETE toutes les tables connues
#     via les mappings — si fake_site_aware_entity est mappe mais absent
#     en DB, le purger crash.
#  3. fixtures -> sync-permissions -> seed-rbac : fixtures:load purge la table
#     permission, donc sync doit passer apres. seed-rbac (matrice RBAC § 2.7)
#     passe ensuite, car attachMatrix() exige les permissions en base. Les
#     comptes demo sont crees par RbacDemoFixtures au load (sans la matrice,
#     attachee ici). Cf. ERP-74.
#  4. recreation des index partiels uniques : schema:update drop les index
#     orphelins du mapping ORM. Les index partiels (LOWER + WHERE) ne sont pas
#     exprimables via les attributs Doctrine ORM (fonctionnel + partiel), donc
#     ils disparaissent apres schema:update. On les recree par dbal:run-sql :
#       - `uq_category_name_type_active` (M0 Catalog) : tests RG-1.07.
#       - `uq_category_code` (Catalog ERP-78) : unicite du code categorie parmi
#         les actifs (slug du nom), pilote RG-1.03/1.29.
#       - `uq_client_company_name_active` (M1 Commercial) : unicite nom societe
#         parmi actifs non archives/non supprimes (RG-1.16), tests ERP-55.
#     Sans ces restores, les POST doublons remontent 201 au lieu de 409.
#  5. app:apply-column-comments : meme cause, schema:update drop les COMMENT
#     ON COLUMN/TABLE des tables managees par l'ORM (le mapping PHP ne porte
#     pas d'attribut options['comment']). On rejoue le catalogue partage
#     `ColumnCommentsCatalog` pour conserver la documentation SQL exigee par
#     le test architecture ColumnsHaveSqlCommentTest (ERP-67).
test-db-setup:
	$(SYMFONY_CONSOLE) doctrine:database:create --env=test --if-not-exists
	$(SYMFONY_CONSOLE) doctrine:migrations:migrate --env=test --no-interaction
	$(SYMFONY_CONSOLE) doctrine:schema:update --env=test --force
	$(SYMFONY_CONSOLE) --env=test --no-interaction app:apply-column-comments
	$(SYMFONY_CONSOLE) --env=test --no-interaction doctrine:fixtures:load
	$(SYMFONY_CONSOLE) --env=test --no-interaction app:sync-permissions
	$(SYMFONY_CONSOLE) --env=test --no-interaction app:seed-rbac
	$(SYMFONY_CONSOLE) --env=test dbal:run-sql "CREATE UNIQUE INDEX IF NOT EXISTS uq_category_name_type_active ON category (LOWER(name), category_type_id) WHERE deleted_at IS NULL"
	$(SYMFONY_CONSOLE) --env=test dbal:run-sql "CREATE UNIQUE INDEX IF NOT EXISTS uq_category_code ON category (code) WHERE deleted_at IS NULL"
	$(SYMFONY_CONSOLE) --env=test dbal:run-sql "CREATE UNIQUE INDEX IF NOT EXISTS uq_client_company_name_active ON client (LOWER(company_name)) WHERE is_archived = FALSE AND deleted_at IS NULL"
	$(SYMFONY_CONSOLE) --env=test dbal:run-sql "CREATE UNIQUE INDEX IF NOT EXISTS uq_supplier_company_name_active ON supplier (LOWER(company_name)) WHERE is_archived = FALSE AND deleted_at IS NULL"

fixtures:
	$(SYMFONY_CONSOLE) --no-interaction doctrine:fixtures:load

# Synchronise le catalogue de permissions RBAC avec les declarations
# des modules actifs (CoreModule::permissions() etc.). Idempotent.
sync-permissions:
	$(SYMFONY_CONSOLE) --no-interaction app:sync-permissions

# Seed RBAC metier : roles (bureau/compta/commerciale/usine) + matrice § 2.7
# (+ comptes demo en dev). Idempotent et NON destructif. A lancer APRES
# sync-permissions (attachMatrix exige les permissions en base). Les comptes
# demo dev sont deja crees par RbacDemoFixtures (make fixtures) ; ici on attache
# la matrice (les permissions etaient purgees au moment du load fixtures).
# En recette/prod, c'est cette commande (avec/sans --with-demo-users) qui seede.
seed-rbac:
	$(SYMFONY_CONSOLE) --no-interaction app:seed-rbac

# Attention, supprime votre bdd local
db-reset:
	$(DOCKER_COMPOSE) down -v
	$(DOCKER_COMPOSE) up -d
	$(MAKE) wait
	$(SYMFONY_CONSOLE) doctrine:database:create --if-not-exists
	$(MAKE) migration-migrate
	$(MAKE) fixtures
	$(MAKE) sync-permissions
	$(MAKE) seed-rbac
	$(MAKE) test-db-setup

# Restart la bdd
db-restart:
	$(DOCKER_COMPOSE) down
	$(DOCKER_COMPOSE) up -d

cache-clear:
	$(SYMFONY_CONSOLE) cache:clear

copy-git-hook:
	$(EXEC_PHP) cp pre-commit .git/hooks/
	$(EXEC_PHP) cp commit-msg .git/hooks/
	$(EXEC_PHP) chmod a+x .git/hooks/pre-commit
	$(EXEC_PHP) chmod a+x .git/hooks/commit-msg

shell:
	$(EXEC_PHP_INTERACTIVE) bash

shell-root:
	$(EXEC_PHP_INTERACTIVE_ROOT) bash

# Suivi temps réel des logs dev
logs-dev:
	$(EXEC_PHP_INTERACTIVE) sh -lc "tail -f var/log/dev.log"

# Force la version node
node-use:
	bash -lc 'source "$$HOME/.nvm/nvm.sh" && nvm install && nvm use'

# Utilisé par le pre-commit pour fix les fichiers modifiés
php-cs-fixer-allow-risky:
	@echo "Fixing files: $(FILES)"
	$(EXEC_PHP_CS_FIXER) fix --config=.php-cs-fixer.dist.php --allow-risky=yes $(FILES)

# Dry-run du fixer : echec si au moins un fichier n'est pas conforme.
# Utilise par la CI (Gitea pull_request) et avant un push manuel.
php-cs-fixer-check:
	$(EXEC_PHP_CS_FIXER) fix --config=.php-cs-fixer.dist.php --allow-risky=yes --dry-run --diff $(FILES)

test:
	$(EXEC_PHP) php -d memory_limit="512M" vendor/bin/phpunit $(FILES)

# Lance l'ensemble des tests (PHPUnit back + Vitest front)
test-all: test nuxt-test

wait:
	sleep 10
