#!/usr/bin/env bash
# =============================================================================
#  03-redeploy.sh
#  À EXÉCUTER SUR LE SERVEUR DE PROD.
#
#  Reset + redéploiement avec la nouvelle architecture (2 images, pas de sync).
#  Variables :
#    KPLAN_IMAGE_TAG  : tag commun PHP + nginx (ex: 202605041930-abc1234)
#    STACK_DIR        : répertoire stack.yaml + .env.stack (def: /opt/kplan)
# =============================================================================

set -euo pipefail

STACK_NAME=kplan
STACK_DIR="${STACK_DIR:-/opt/kplan}"
ENV_FILE="${STACK_DIR}/.env.stack"
STACK_FILE="${STACK_DIR}/stack.yaml"
STACK_RESOLVED=/tmp/stack.resolved.yaml

PHP_IMAGE="${PHP_IMAGE:-massambafall92/kplan-www}"
NGINX_IMAGE="${NGINX_IMAGE:-massambafall92/kplan-www-nginx}"
PHP_TIMEOUT=180

if [ -t 1 ]; then
    C_BLUE='\033[1;34m'; C_GREEN='\033[1;32m'; C_YELLOW='\033[1;33m'
    C_RED='\033[1;31m';  C_DIM='\033[2m';      C_RESET='\033[0m'
else
    C_BLUE=''; C_GREEN=''; C_YELLOW=''; C_RED=''; C_DIM=''; C_RESET=''
fi
log()  { printf "${C_BLUE}▸ %s${C_RESET}\n" "$*"; }
ok()   { printf "${C_GREEN}✓ %s${C_RESET}\n" "$*"; }
warn() { printf "${C_YELLOW}⚠ %s${C_RESET}\n" "$*"; }
err()  { printf "${C_RED}✗ %s${C_RESET}\n" "$*" >&2; }

[ "$(id -u)" -eq 0 ] || { err "Lance ce script en root"; exit 1; }
[ -n "${KPLAN_IMAGE_TAG:-}" ] || { err "Variable KPLAN_IMAGE_TAG non définie"; exit 1; }

PHP_FULL="${PHP_IMAGE}:${KPLAN_IMAGE_TAG}"
NGINX_FULL="${NGINX_IMAGE}:${KPLAN_IMAGE_TAG}"

[ -f "$STACK_FILE" ] || { err "$STACK_FILE introuvable"; exit 1; }
[ -f "$ENV_FILE" ]   || { err "$ENV_FILE introuvable"; exit 1; }

# Backup récent ?
LATEST_BACKUP=$(ls -td /opt/kplan/backups/*/ 2>/dev/null | head -1 || true)
if [ -z "$LATEST_BACKUP" ]; then
    err "Aucun backup — lance d'abord 01-backup-prod.sh"
    exit 1
fi
ok "Backup : $LATEST_BACKUP"

# Pull + valid des deux images
for IMG in "$PHP_FULL" "$NGINX_FULL"; do
    log "Pull + validation $IMG..."
    docker pull "$IMG" >/dev/null || { err "$IMG inaccessible"; exit 1; }

    COUNT=$(docker run --rm --entrypoint sh "$IMG" -c '
        APP_CSS=$(find /var/www/public/build -name "app.*.css" 2>/dev/null | head -1)
        [ -z "$APP_CSS" ] && exit 1
        grep -c "osep-" "$APP_CSS"
    ' 2>/dev/null || echo 0)
    [ "$COUNT" -ge 1000 ] || { err "$IMG bundle anémique ($COUNT)"; exit 1; }
    ok "$IMG : $COUNT classes osep-"
done

echo
warn "Tu vas :"
echo "  • Arrêter le stack $STACK_NAME"
echo "  • Redéployer avec :"
echo "      php   = $PHP_FULL"
echo "      nginx = $NGINX_FULL"
echo "  • Volumes PRÉSERVÉS : kplan_data, kplan_uploads, rabbitmq_data, redis_data"
echo
printf "${C_YELLOW}? Confirmer (taper REDEPLOY) : ${C_RESET}"
read -r REPLY
[ "$REPLY" = "REDEPLOY" ] || { err "Annulé"; exit 1; }

# Phase 1 — stop
log "Phase 1 : arrêt du stack..."
if docker stack ls --format '{{.Name}}' | grep -q "^${STACK_NAME}$"; then
    docker stack rm "$STACK_NAME"
    for i in $(seq 1 30); do
        REMAINING=$(docker ps -q --filter "label=com.docker.stack.namespace=${STACK_NAME}" | wc -l)
        [ "$REMAINING" -eq 0 ] && break
        printf "."
        sleep 2
    done
    echo
    ok "Stack arrêté"
fi

# Cleanup volumes obsolètes (kplan_public n'existe plus dans la nouvelle archi)
docker volume rm kplan_public 2>/dev/null || true
docker volume rm "${STACK_NAME}_public" 2>/dev/null || true

# Phase 2 — env + deploy
log "Phase 2 : mise à jour .env.stack..."
for k in KPLAN_IMAGE_PHP KPLAN_IMAGE_NGINX; do
    val="$PHP_FULL"
    [ "$k" = "KPLAN_IMAGE_NGINX" ] && val="$NGINX_FULL"
    if grep -q "^${k}=" "$ENV_FILE"; then
        sed -i "s|^${k}=.*|${k}=${val}|" "$ENV_FILE"
    else
        echo "${k}=${val}" >> "$ENV_FILE"
    fi
done
ok "Env mis à jour"

sed -i 's/\r$//' "$ENV_FILE" || true
set -a; . "$ENV_FILE"; set +a
envsubst < "$STACK_FILE" > "$STACK_RESOLVED"

if [ -n "${DOCKERHUB_USERNAME:-}" ] && [ -n "${DOCKERHUB_TOKEN:-}" ]; then
    echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin >/dev/null
fi

log "Phase 2 : déploiement..."
docker stack deploy \
    -c "$STACK_RESOLVED" \
    --with-registry-auth \
    --prune \
    "$STACK_NAME"

# Phase 3 — wait services
log "Phase 3 : attente php + nginx ready (max ${PHP_TIMEOUT}s)..."
for i in $(seq 1 $((PHP_TIMEOUT / 5))); do
    PHP_OK=$(docker service ps "${STACK_NAME}_php" --format '{{.CurrentState}}' --no-trunc 2>/dev/null | grep -c "^Running" || true)
    NGINX_OK=$(docker service ps "${STACK_NAME}_nginx" --format '{{.CurrentState}}' --no-trunc 2>/dev/null | grep -c "^Running" || true)

    if [ "$PHP_OK" -ge 1 ] && [ "$NGINX_OK" -ge 1 ]; then
        echo
        ok "php=$PHP_OK running, nginx=$NGINX_OK running"
        break
    fi
    printf "."
    sleep 5
done
echo

# Phase 4 — smoke tests
log "Phase 4 : smoke tests..."

# Test HTTP
HTTP_CODE=$(curl -fsS -o /dev/null -w "%{http_code}" http://localhost/ 2>/dev/null || echo 000)
[ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ] && ok "App répond HTTP $HTTP_CODE" || warn "App répond HTTP $HTTP_CODE"

# Test CSS
CSS_CODE=$(curl -fsS -o /dev/null -w "%{http_code}" "http://localhost/build/manifest.json" 2>/dev/null || echo 000)
[ "$CSS_CODE" = "200" ] && ok "manifest.json servi (HTTP $CSS_CODE)" || warn "manifest.json HTTP $CSS_CODE"

# Cache writable
PHP_CID=$(docker ps -q --filter "label=com.docker.swarm.service.name=${STACK_NAME}_php" | head -1)
if [ -n "$PHP_CID" ]; then
    if docker exec --user www-data "$PHP_CID" sh -c 'touch /var/www/var/cache/prod/.t && rm /var/www/var/cache/prod/.t' 2>/dev/null; then
        ok "Cache Symfony writable par www-data"
    else
        warn "Cache non writable — fix manuel requis"
    fi
fi

echo
ok "=== Redéploiement terminé ==="
docker stack services "$STACK_NAME"
