#!/bin/sh
#
# Deploiement d'Ecole Haiti sur school.kopba.org (Namecheap, cPanel).
#
#   sh deploy/hebergement-mutualise/namecheap.sh --premiere   premiere mise en ligne
#   sh deploy/hebergement-mutualise/namecheap.sh              mise a jour
#
# A lancer depuis la racine du projet, apres `deploy\build-release.ps1`.
# Les reglages de connexion sont lus dans un fichier HORS du depot :
# /c/dev/.cles-deploiement/ecole-haiti.conf  (voir PREMIERE-FOIS.md).
#
# Le script s'arrete a la premiere erreur : sur un hebergement partage, une
# commande qui echoue en silence laisse une application a moitie deployee,
# ce qui est pire qu'une application absente.
#
set -eu

CONF="${ECOLE_CONF:-/c/dev/.cles-deploiement/ecole-haiti.conf}"

if [ ! -f "$CONF" ]; then
    echo "Fichier de reglages absent : $CONF" >&2
    echo "Creez-le (voir deploy/hebergement-mutualise/PREMIERE-FOIS.md)." >&2
    exit 1
fi

# HOTE, PORT, UTILISATEUR, CLE, RACINE, DOMAINE
. "$CONF"

: "${HOTE:?}" "${PORT:?}" "${UTILISATEUR:?}" "${CLE:?}" "${RACINE:?}" "${DOMAINE:?}"

# `ea-php83` n'est PAS dans le PATH d'une session SSH non interactive sur cet
# hebergeur : les commandes en sortaient silencieusement vides.
PHP="${PHP:-/usr/local/bin/php}"

SSH="ssh -i $CLE -p $PORT -o IdentitiesOnly=yes $UTILISATEUR@$HOTE"
SCP="scp -i $CLE -P $PORT -o IdentitiesOnly=yes"

PREMIERE=0
for arg in "$@"; do
    case "$arg" in
        --premiere) PREMIERE=1 ;;
        *) echo "Option inconnue : $arg" >&2; exit 1 ;;
    esac
done

dire() { printf '\n== %s\n' "$1"; }

# ------------------------------------------------------------- Controles ---

dire "Controles avant de partir"

# On expedie l'archive de release : elle contient le code commite, `vendor`
# construit --no-dev et les assets compiles. Elle a ete produite par
# build-release.ps1, qui refuse un depot sale.
ARCHIVE="$(ls -t dist/ecole-haiti-*.zip 2>/dev/null | grep -v -- '-hebergement' | head -1 || true)"

if [ -z "$ARCHIVE" ]; then
    echo "Aucune archive dans dist/ : lancez d'abord" >&2
    echo "  powershell -ExecutionPolicy Bypass -File deploy\\build-release.ps1" >&2
    exit 1
fi

echo "Archive : $ARCHIVE ($(du -h "$ARCHIVE" | cut -f1))"

if [ -n "$(git status --porcelain)" ]; then
    echo "" >&2
    echo "Le depot a des modifications non commitees :" >&2
    git status --short >&2
    echo "" >&2
    echo "Elles ne sont PAS dans l'archive. Commitez puis reconstruisez." >&2
    exit 1
fi

$SSH "echo 'Connexion SSH : OK'"
$SSH "$PHP -v | head -1"

# ------------------------------------------------------------ Sauvegarde ---

dire "Sauvegarde de l'etat actuel, avant de toucher a quoi que ce soit"

# Hors du dossier de l'application : un redeploiement ne doit pas emporter
# les sauvegardes avec ce qu'elles protegent.
SAUVEGARDES="/home/$UTILISATEUR/sauvegardes-ecole"
$SSH "mkdir -p $RACINE $SAUVEGARDES && chmod 700 $SAUVEGARDES"

# La presence d'`artisan` ne dit pas que l'application est installee : au
# deuxieme passage d'une premiere mise en ligne, le fichier est la mais les
# tables n'existent pas. On interroge la table des migrations, seul temoin
# fiable d'une base en service.
if $SSH "test -f $RACINE/.env && cd $RACINE && $PHP artisan migrate:status >/dev/null 2>&1"; then
    $SSH "cd $RACINE && $PHP artisan school:backup --keep=10 && cp -f storage/backups/\$(ls -t storage/backups | head -1) $SAUVEGARDES/"
    echo "Copie hors de l'application : $SAUVEGARDES"
else
    echo "Base pas encore installee : rien a sauvegarder."
fi

# ------------------------------------------------------------- Transfert ---

dire "Transfert de l'application"

NOM="$(basename "$ARCHIVE")"
$SCP "$ARCHIVE" "$UTILISATEUR@$HOTE:/home/$UTILISATEUR/"

# -o : ecrase les fichiers existants sans demander. `.env` et `storage/` ne
# sont pas dans l'archive, ils survivent donc intacts.
$SSH "cd $RACINE && unzip -oq /home/$UTILISATEUR/$NOM && rm -f /home/$UTILISATEUR/$NOM"

dire "Ceinture de securite a la racine du code"

# Si la racine du domaine est un jour mal reglee, Apache lira ce fichier et
# refusera de servir le .env et les sauvegardes. Quand elle est juste, Apache
# ne le lit jamais : il ne coute rien.
$SCP deploy/hebergement-mutualise/racine.htaccess "$UTILISATEUR@$HOTE:$RACINE/.htaccess"

# Et le contrepoids, qui ne vaut que pour le dossier servi : cPanel autorise
# les surcharges sur tout le repertoire personnel, donc Apache applique le
# .htaccess du parent a public/.
$SSH "grep -q 'Require all granted' $RACINE/public/.htaccess || printf '\n<IfModule mod_authz_core.c>\n    Require all granted\n</IfModule>\n' >> $RACINE/public/.htaccess"

# ------------------------------------------------------------------ Env ---

if ! $SSH "test -f $RACINE/.env"; then
    dire "Reglages de production"
    echo "" >&2
    echo "Le fichier .env n'existe pas encore sur le serveur. Deposez-le :" >&2
    echo "" >&2
    echo "  $SCP deploy/serveur-linux/env.production.example \\" >&2
    echo "      $UTILISATEUR@$HOTE:$RACINE/.env" >&2
    echo "" >&2
    echo "puis renseignez DB_* et APP_URL avant de relancer." >&2
    echo "Voir deploy/hebergement-mutualise/PREMIERE-FOIS.md." >&2
    exit 1
fi

# --------------------------------------------------------------- Schema ---

dire "Decouverte des paquets"

# Le manifeste n'est pas expedie : il decrit la machine qui a construit.
$SSH "cd $RACINE && $PHP artisan package:discover --ansi"

if [ "$PREMIERE" = "1" ]; then
    dire "Cle de l'application"

    # Sans --force : regenerer la cle d'une installation en service rendrait
    # illisibles toutes les sessions.
    $SSH "cd $RACINE && grep -q '^APP_KEY=base64:' .env || $PHP artisan key:generate"
fi

dire "Migrations"

$SSH "cd $RACINE && $PHP artisan migrate --force"

# --------------------------------------------------------------- Droits ---

dire "Droits sur les dossiers inscriptibles"

# 755 et non 777 : PHP tourne sous votre utilisateur, et 777 rendrait ces
# fichiers inscriptibles par les autres comptes du serveur.
$SSH "cd $RACINE && chmod -R 755 storage bootstrap/cache && chmod 600 .env"

dire "Mise en cache"

# La configuration d'abord : les routes et les vues la lisent.
$SSH "cd $RACINE && $PHP artisan config:cache && $PHP artisan route:cache && $PHP artisan view:cache"
$SSH "cd $RACINE && $PHP artisan storage:link 2>/dev/null || true"

# ------------------------------------------------------------- Controles ---

if [ "$PREMIERE" = "1" ]; then
    dire "Etablissement"
    echo "Lancez maintenant, en interactif :"
    echo ""
    echo "  $SSH -t 'cd $RACINE && $PHP artisan school:install'"
    echo ""
else
    dire "Controle d'aptitude"
    $SSH "cd $RACINE && $PHP artisan school:check"
fi

dire "Sonde HTTP"

# La seule preuve que la racine du domaine pointe bien sur public/ : si elle
# pointait un niveau au-dessus, on verrait une liste de fichiers ou un 403.
CODE="$(curl -s -o /dev/null -w '%{http_code}' "https://$DOMAINE/login" || echo '000')"
echo "https://$DOMAINE/login -> $CODE"
[ "$CODE" = "200" ] || echo "ATTENTION : 200 attendu. Verifiez la racine du domaine et les journaux." >&2

dire "Termine — https://$DOMAINE"
