# ===========================================================
#   Pipeline GitLab CI pour missioflow-SuperAdmin
#   Calque structurel sur missioflow-app/.gitlab-ci.yml — pattern
#   build-on-VPS via SSH (pas de registry intermédiaire) + stack Swarm.
# ===========================================================

stages:
  - test
  - deploy

variables:
  GIT_DEPTH: "20"
  NODE_VERSION: "22"

# -----------------------------------------------------------
# Étape test : lint + build smoke test
# -----------------------------------------------------------
test:
  stage: test
  image: node:22-alpine
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
    - if: $CI_COMMIT_BRANCH == 'main'
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - .npm/
  before_script:
    - npm ci --cache .npm --prefer-offline --no-audit --no-fund
  script:
    - npm run lint
    # Build standalone — vérifie que le routing, les types et la config sont
    # cohérents. Le build n'a pas besoin de API_BASE_URL (lecture lazy au runtime).
    - npm run build
  artifacts:
    when: on_failure
    paths:
      - .next/build-trace/

# -----------------------------------------------------------
# Étape deploy : push main → build sur VPS → docker stack deploy
# -----------------------------------------------------------
deploy_superadmin_vps:
  stage: deploy
  image: alpine:3.20
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
  before_script:
    - apk add --no-cache openssh-client bash coreutils
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - |
      if [ -n "$OVH_SSH_PRIVATE_KEY_B64" ]; then
        echo "$OVH_SSH_PRIVATE_KEY_B64" | base64 -d > ~/.ssh/id_ed25519
      elif [ -n "$OVH_SSH_PRIVATE_KEY" ]; then
        printf "%s\n" "$OVH_SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
      else
        echo "ERREUR: OVH_SSH_PRIVATE_KEY_B64 ou OVH_SSH_PRIVATE_KEY doit etre defini"
        exit 1
      fi
    - chmod 600 ~/.ssh/id_ed25519
    - ssh-keyscan -H "$OVH_SSH_HOST" >> ~/.ssh/known_hosts
  script:
    - export SUPERADMIN_DEPLOY_PATH="${SUPERADMIN_DEPLOY_PATH:-/home/${OVH_SSH_USER}/missioflow-superadmin}"
    - echo "Deploiement panel vers ${OVH_SSH_USER}@${OVH_SSH_HOST}:${SUPERADMIN_DEPLOY_PATH}"

    # 0) Générer .env.superadmin.secrets à partir des GitLab CI variables.
    # Ce fichier voyage dans le tar mais n'est JAMAIS commité (cf .gitignore).
    # Toutes les vars peuvent être absentes — le compose a des défauts vides
    # ; le panel rendra simplement une erreur "Variables DB manquantes" sur
    # les pages qui ont besoin de la DB. Ça évite de bloquer le déploiement
    # quand seul un sous-ensemble est configuré.
    - |
      cat > .env.superadmin.secrets <<EOF
      DB_HOST=${DB_HOST:-}
      DB_PORT=${DB_PORT:-3306}
      DB_NAME=${DB_NAME:-}
      DB_USER=${DB_USER:-}
      DB_PASSWORD=${DB_PASSWORD:-}
      SUPERADMIN_IP_ALLOWLIST=${SUPERADMIN_IP_ALLOWLIST:-}
      MF_INTERNAL_NETWORK=${MF_INTERNAL_NETWORK:-missioflow-prod_prod-net}
      MISSIOFLOW_SITE_REBUILD_TRIGGER_TOKEN=${MISSIOFLOW_SITE_REBUILD_TRIGGER_TOKEN:-}
      GITLAB_BASE_URL=${GITLAB_BASE_URL:-}
      EOF
    - chmod 600 .env.superadmin.secrets
    - echo "Secrets file généré ($(wc -l < .env.superadmin.secrets) lignes)."

    # 1) Préparer le dossier distant (créé au 1er deploy)
    - |
      ssh "$OVH_SSH_USER@$OVH_SSH_HOST" "
        set -e
        if mkdir -p '${SUPERADMIN_DEPLOY_PATH}' 2>/dev/null; then
          echo 'Dossier deploy cree sans sudo'
        else
          sudo mkdir -p '${SUPERADMIN_DEPLOY_PATH}'
          sudo chown -R '${OVH_SSH_USER}':'${OVH_SSH_USER}' '${SUPERADMIN_DEPLOY_PATH}'
          echo 'Dossier deploy cree avec sudo'
        fi
      "

    # 2) Copier le code du commit courant (sans .git ni node_modules ni .next)
    - tar --exclude='.git' --exclude='node_modules' --exclude='.next' -czf /tmp/superadmin-src.tgz .
    - scp /tmp/superadmin-src.tgz "$OVH_SSH_USER@$OVH_SSH_HOST:${SUPERADMIN_DEPLOY_PATH}/superadmin-src.tgz"
    - ssh "$OVH_SSH_USER@$OVH_SSH_HOST" "cd '${SUPERADMIN_DEPLOY_PATH}' && tar -xzf superadmin-src.tgz && rm -f superadmin-src.tgz"

    # 3) Build de l'image sur le VPS + stack deploy
    - |
      ssh "$OVH_SSH_USER@$OVH_SSH_HOST" "
        cd '${SUPERADMIN_DEPLOY_PATH}'

        if docker info >/dev/null 2>&1; then
          DOCKER_CMD='docker'
        else
          DOCKER_CMD='sudo docker'
        fi

        SWARM_STATE=\$(\$DOCKER_CMD info --format '{{.Swarm.LocalNodeState}}')
        if [ \"\$SWARM_STATE\" != 'active' ]; then
          echo 'ERREUR: ce VPS n est pas en mode Swarm actif'
          exit 1
        fi

        # Charger .env.superadmin (statique) puis .env.superadmin.secrets
        # (généré par CI à partir des GitLab CI variables) — l'ordre fait que
        # les secrets l'emportent sur les valeurs commitées si conflit.
        for f in ./.env.superadmin ./.env.superadmin.secrets; do
          [ -f \"\$f\" ] || continue
          while IFS= read -r line; do
            case \"\$line\" in
              ''|\#*) continue ;;
            esac
            key=\"\${line%%=*}\"
            value=\"\${line#*=}\"
            export \"\$key=\$value\"
          done < \"\$f\"
        done

        # Tag par SHA court — sinon :latest est mutable et Swarm ne recree
        # pas les tâches même si l'image locale a changé (cf. missioflow-app).
        APP_IMAGE='missioflow-superadmin:${CI_COMMIT_SHORT_SHA}'
        export APP_IMAGE

        SUPERADMIN_STACK_NAME='${SUPERADMIN_STACK_NAME:-missioflow-superadmin}'

        echo \"Build image: \$APP_IMAGE\"
        \$DOCKER_CMD build --pull -t \"\$APP_IMAGE\" .
        \$DOCKER_CMD image inspect \"\$APP_IMAGE\" >/dev/null 2>&1 || { echo 'ERREUR: Image non creee'; exit 1; }
        \$DOCKER_CMD tag \"\$APP_IMAGE\" missioflow-superadmin:latest

        # Vérifier que le network interne missioflow-prod est bien attachable
        # depuis cette stack avant le deploy. Si missioflow-prod n'est pas
        # déployé, ou si le network n'est pas externe-attachable, on log un
        # warning sans bloquer (le panel boot quand même, juste sans DB).
        MF_INTERNAL_NETWORK_NAME=\"\${MF_INTERNAL_NETWORK:-missioflow-prod_prod-net}\"
        if ! \$DOCKER_CMD network inspect \"\$MF_INTERNAL_NETWORK_NAME\" >/dev/null 2>&1; then
          echo \"WARN: network \$MF_INTERNAL_NETWORK_NAME introuvable — le panel ne pourra pas atteindre MySQL prod. Le service Swarm refusera de se lancer.\"
        fi

        \$DOCKER_CMD stack deploy --with-registry-auth --compose-file docker-compose.superadmin.yml \"\$SUPERADMIN_STACK_NAME\"
        \$DOCKER_CMD stack services \"\$SUPERADMIN_STACK_NAME\"

        # Cleanup : ne pas laisser .env.superadmin.secrets traîner sur le VPS
        # après le deploy — les vars sont déjà bakées dans la spec du service
        # Swarm (visibles via docker service inspect uniquement par root).
        rm -f ./.env.superadmin.secrets

        # Cleanup images dangling (les anciens tags par SHA restent pour rollback manuel)
        \$DOCKER_CMD image prune -f >/dev/null 2>&1 || true

        # Vérification routage Traefik
        TRAEFIK_NET=\"\${TRAEFIK_NETWORK:-traefik-public}\"
        \$DOCKER_CMD network inspect \"\$TRAEFIK_NET\" >/dev/null

        APP_SERVICE=\"\${SUPERADMIN_STACK_NAME}_app\"
        SERVICE_LABELS=\$(\$DOCKER_CMD service inspect \"\$APP_SERVICE\" --format '{{json .Spec.Labels}}')
        TASK_LABELS=\$(\$DOCKER_CMD service inspect \"\$APP_SERVICE\" --format '{{json .Spec.TaskTemplate.ContainerSpec.Labels}}')
        echo \"\$SERVICE_LABELS \$TASK_LABELS\" | grep -q 'traefik.http.routers.missioflow-superadmin.rule' \
          || { echo 'ERREUR: label router missioflow-superadmin absent'; exit 1; }
        echo \"\$SERVICE_LABELS \$TASK_LABELS\" | grep -q 'sysop.missioflow.fr' \
          || { echo 'ERREUR: hostname sysop.missioflow.fr absent des labels'; exit 1; }

        # Health check : attendre que app soit pret
        echo 'Post-deploy : attente app pret...'
        for i in 1 2 3 4 5 6 7 8 9 10; do
          APP_TASK_ID=\$(\$DOCKER_CMD ps --filter label=com.docker.swarm.service.name=\"\$APP_SERVICE\" -q | head -n1)
          if [ -n \"\$APP_TASK_ID\" ] && \$DOCKER_CMD exec \"\$APP_TASK_ID\" wget -qO- http://127.0.0.1:3000/login >/dev/null 2>&1; then
            echo 'Post-deploy OK'
            exit 0
          fi
          sleep 3
        done
        echo 'WARN: health check non confirme apres 30s — vérifier manuellement'
      "
  environment:
    name: superadmin
