# =============================================================================
# WordPress PROD __PROJECT_TITLE__ — ressource « Docker Compose » Coolify.
# -----------------------------------------------------------------------------
# Option 2 : l'image est BUILDÉE EN CI (`.github/workflows/deploy.yml` → GHCR),
# JAMAIS sur l'hôte. Coolify fait `docker compose pull && up -d` et tire le tag
# pointé par WORDPRESS_IMAGE.
#
#   • Image    : env Coolify `WORDPRESS_IMAGE`, ex. ghcr.io/<owner>/<repo>/wordpress:main
#   • Rollback : passer WORDPRESS_IMAGE à un tag SHA (…/wordpress:<sha>) puis redéployer.
#   • DB/Redis : ressources Coolify SÉPARÉES (backups managés), jointes via le
#                réseau `coolify`. Pour une stack 100 % autonome, dé-commente le
#                bloc `db` + `redis` en bas et pointe WORDPRESS_DB_HOST=db / WP_REDIS_HOST=redis.
#
# Les labels Traefik vivent ICI (versionnés, relus en PR) au lieu d'être recopiés
# à la main dans l'UI Coolify. Ils lisent WP_HOST / APP_HOST depuis l'env Coolify.
#
# ⚠️ Pas de rolling update en mode compose Coolify (noms de conteneurs statiques).
#    WordPress est stateful (volume partagé) : le rolling y est de toute façon
#    déconseillé (deux conteneurs sur le même /var/www/html + migrations). Le host
#    `wp.` est DNS-only ; un court blip admin/GraphQL au redeploy est acceptable —
#    le front lit WP en interne et le HTML public est caché à l'edge (SWR).
# =============================================================================
name: __PROJECT_NAME__-wordpress

services:
  wordpress:
    image: ${WORDPRESS_IMAGE:?WORDPRESS_IMAGE manquant (ex. ghcr.io/<owner>/<repo>/wordpress:main)}
    restart: unless-stopped
    environment:
      # Connexion aux ressources Coolify db/redis (résolues sur le réseau `coolify`).
      WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST}
      WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME}
      WORDPRESS_DB_USER: ${WORDPRESS_DB_USER}
      WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
      WP_REDIS_HOST: ${WP_REDIS_HOST}
      WP_REDIS_PASSWORD: ${WP_REDIS_PASSWORD}
      # URLs (lues par la config bakée wp-reactor-config.php via auto_prepend_file).
      WP_HOME: ${WP_HOME}
      WP_SITEURL: ${WP_SITEURL}
      FRONTEND_URL: ${FRONTEND_URL}
      WP_ENVIRONMENT_TYPE: ${WP_ENVIRONMENT_TYPE:-production}
      # NE PAS définir WORDPRESS_CONFIG_EXTRA / WORDPRESS_DEBUG (bakés) — cf. environment.md.
      WP_DEBUG: ${WP_DEBUG:-false}
      # Provisioning au premier démarrage (install core + plugins + thème), lancé
      # par child-entrypoint.sh. Idempotent, donc sans effet aux boots suivants.
      # À 0, il faut repasser par le `docker exec … bootstrap.sh` manuel.
      WP_AUTO_BOOTSTRAP: ${WP_AUTO_BOOTSTRAP:-0}
      # Pas de valeur par défaut ici : le titre humain n'a rien à faire dans le
      # compose, dont toutes les lignes sont des identifiants. Le repli vit dans
      # bootstrap.sh, où c'est bien une valeur.
      WP_SITE_TITLE: ${WP_SITE_TITLE:-}
      WP_ADMIN_USER: ${WP_ADMIN_USER:-admin}
      WP_ADMIN_PASSWORD: ${WP_ADMIN_PASSWORD:-}
      WP_ADMIN_EMAIL: ${WP_ADMIN_EMAIL:-}
    volumes:
      # Conserve core, uploads, plugins tiers. À déclarer « persistant » côté Coolify.
      - wp_data:/var/www/html
    networks:
      coolify:
        # Alias résolu par la webapp en SSR (WORDPRESS_INTERNAL_URL) — versionné ici
        # au lieu du « Network Alias » manuel dans l'UI Coolify.
        aliases:
          - __PROJECT_NAME__-wordpress-internal
    # Liveness : Apache écoute sur :80 (php est présent dans l'image, pas curl).
    healthcheck:
      test: ["CMD-SHELL", "php -r 'exit(@fsockopen(\"127.0.0.1\", 80) ? 0 : 1);'"]
      interval: 15s
      timeout: 5s
      retries: 10
      start_period: 60s
    # Laisse Apache/PHP-FPM drainer les requêtes en cours au redeploy.
    stop_grace_period: 30s
    labels:
      - 'traefik.enable=true'
      - 'traefik.docker.network=coolify'
      - 'traefik.http.services.__PROJECT_NAME__-wordpress.loadbalancer.server.port=80'

      # Médias uploads : cache revalidable (remplaçables à la même URL, non fingerprintés).
      - 'traefik.http.middlewares.__PROJECT_NAME__-wp-uploads-cache.headers.customResponseHeaders.Cache-Control=public, max-age=3600, stale-while-revalidate=86400'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-uploads.rule=Host(`${WP_HOST}`) && PathPrefix(`/wp-content/uploads`)'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-uploads.entrypoints=https'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-uploads.service=__PROJECT_NAME__-wordpress'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-uploads.priority=95'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-uploads.middlewares=__PROJECT_NAME__-wp-uploads-cache'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-uploads.tls=true'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-uploads.tls.certresolver=letsencrypt'

      # Build du thème : noms de fichiers réellement fingerprintés
      # (assets/<name>-<hash>.js) → immutable sans risque.
      - 'traefik.http.middlewares.__PROJECT_NAME__-wp-build-cache.headers.customResponseHeaders.Cache-Control=public, max-age=31536000, immutable'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-build.rule=Host(`${WP_HOST}`) && PathRegexp(`^/wp-content/themes/[^/]+/build/`)'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-build.entrypoints=https'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-build.service=__PROJECT_NAME__-wordpress'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-build.priority=92'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-build.middlewares=__PROJECT_NAME__-wp-build-cache'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-build.tls=true'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-build.tls.certresolver=letsencrypt'

      # Core WordPress et plugins : versionnés par `?ver=`, PAS par le nom de
      # fichier. Or ce `?ver=` ne bouge pas pour les fichiers que la release ne
      # modifie pas — `private-apis.min.js` a gardé le sien d'une majeure à
      # l'autre. En `immutable`, le navigateur ne revalide jamais : il mélangeait
      # un `private-apis` de l'ancien core avec un `block-editor` du nouveau, et
      # l'éditeur Gutenberg ne démarrait plus (« Cannot unlock an undefined
      # object »). D'où une revalidation courte ici, et l'immutable réservé aux
      # vrais noms fingerprintés ci-dessus.
      - 'traefik.http.middlewares.__PROJECT_NAME__-wp-assets-cache.headers.customResponseHeaders.Cache-Control=public, max-age=600, stale-while-revalidate=86400'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-assets.rule=Host(`${WP_HOST}`) && (PathPrefix(`/wp-includes`) || PathPrefix(`/wp-content`))'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-assets.entrypoints=https'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-assets.service=__PROJECT_NAME__-wordpress'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-assets.priority=90'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-assets.middlewares=__PROJECT_NAME__-wp-assets-cache'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-assets.tls=true'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-assets.tls.certresolver=letsencrypt'

      # SEO (robots.txt + sitemaps) servis sur le host FRONT → WordPress.
      # NB : `\d*` couvre la pagination Yoast (product-sitemap1.xml…). Le `$` final est
      # échappé `$$` (sinon compose l'interpole) → Traefik reçoit bien l'ancre de fin.
      - 'traefik.http.routers.__PROJECT_NAME__-wp-seo.rule=Host(`${APP_HOST}`) && (Path(`/robots.txt`) || Path(`/sitemap_index.xml`) || PathRegexp(`-sitemap\d*\.(xml|xsl)$$`))'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-seo.entrypoints=https'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-seo.service=__PROJECT_NAME__-wordpress'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-seo.priority=100'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-seo.tls=true'
      - 'traefik.http.routers.__PROJECT_NAME__-wp-seo.tls.certresolver=letsencrypt'

      # Catch-all WordPress (admin, /graphql, /wp-json…) sur son host dédié.
      - 'traefik.http.routers.__PROJECT_NAME__-wordpress.rule=Host(`${WP_HOST}`)'
      - 'traefik.http.routers.__PROJECT_NAME__-wordpress.entrypoints=https'
      - 'traefik.http.routers.__PROJECT_NAME__-wordpress.service=__PROJECT_NAME__-wordpress'
      - 'traefik.http.routers.__PROJECT_NAME__-wordpress.priority=10'
      - 'traefik.http.routers.__PROJECT_NAME__-wordpress.tls=true'
      - 'traefik.http.routers.__PROJECT_NAME__-wordpress.tls.certresolver=letsencrypt'

networks:
  coolify:
    external: true

volumes:
  wp_data:

# --- Stack 100 % autonome (optionnel) --------------------------------------
# Dé-commente pour embarquer DB + Redis dans CE compose (une seule ressource
# Coolify, plus de DB managée séparée — tu gères alors les backups toi-même).
# Pointe aussi WORDPRESS_DB_HOST=db et WP_REDIS_HOST=redis côté env Coolify.
#
#  db:
#    image: mariadb:11
#    restart: unless-stopped
#    environment:
#      MARIADB_DATABASE: ${WORDPRESS_DB_NAME}
#      MARIADB_USER: ${WORDPRESS_DB_USER}
#      MARIADB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
#      MARIADB_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
#    volumes:
#      - db_data:/var/lib/mysql
#    networks: [coolify]
#    healthcheck:
#      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
#      interval: 10s
#      timeout: 5s
#      retries: 20
#
#  redis:
#    image: redis:7-alpine
#    restart: unless-stopped
#    command: ["redis-server", "--requirepass", "${WP_REDIS_PASSWORD}"]
#    networks: [coolify]
#
# volumes:
#   db_data:
