#!/usr/bin/env bash
# Activates an uploaded release on the server with a zero-downtime symlink switch (ADR-045).
#
#   remote-deploy.sh <base_path> <release>      activate releases/<release>
#   remote-deploy.sh <base_path> --rollback     switch back to the previous release
#
# Layout:
#   <base>/releases/<release>/   code + vendor + public/build (uploaded by CI)
#   <base>/shared/.env           environment (created once by hand, never in git)
#   <base>/shared/storage/       uploads, the private CV, logs, framework caches (persist across releases)
#   <base>/current -> releases/<release>   web root is <base>/current/public
set -euo pipefail

BASE="${1:?base path required}"
TARGET="${2:?release name or --rollback required}"
KEEP_RELEASES="${KEEP_RELEASES:-5}"
# PHP CLI to use. On cPanel the default `php` may not be 8.4: set PHP_BIN (e.g. /opt/cpanel/ea-php84/root/usr/bin/php).
PHP="${PHP_BIN:-php}"
cd "$BASE"

# Always operates in $BASE (the caller may have cd'd into a release): relative target, atomic rename.
switch_to() {
    (cd "$BASE" && ln -sfn "releases/$1" current.next && mv -Tf current.next current)
}

reload() {
    "$PHP" "$BASE/current/artisan" queue:restart || true
    if [ -n "${RELOAD_COMMAND:-}" ]; then eval "$RELOAD_COMMAND"; fi   # e.g. reload PHP-FPM to clear OPcache
}

if [ "$TARGET" = "--rollback" ]; then
    CURRENT="$(basename "$(readlink current)")"
    PREVIOUS="$(ls -1t releases | grep -vx "$CURRENT" | head -n 1 || true)"
    [ -n "$PREVIOUS" ] || { echo "No previous release to roll back to." >&2; exit 1; }
    switch_to "$PREVIOUS"
    reload
    echo "Rolled back to $PREVIOUS (from $CURRENT)."
    exit 0
fi

RELEASE_DIR="$BASE/releases/$TARGET"
[ -d "$RELEASE_DIR" ] || { echo "Release $RELEASE_DIR not found." >&2; exit 1; }
[ -f "$BASE/shared/.env" ] || { echo "Missing $BASE/shared/.env — create it first (docs/DEPLOYMENT.md §11)." >&2; exit 1; }

# Shared state, created on the first deploy.
mkdir -p "$BASE/shared/storage/app/public" "$BASE/shared/storage/app/private/documents" \
         "$BASE/shared/storage/framework/cache" "$BASE/shared/storage/framework/sessions" \
         "$BASE/shared/storage/framework/views" "$BASE/shared/storage/logs"

cd "$RELEASE_DIR"
ln -sfn "$BASE/shared/.env" .env
rm -rf storage && ln -sfn "$BASE/shared/storage" storage
mkdir -p bootstrap/cache

# Host-specific Apache directives (e.g. cPanel's MultiPHP handler selecting ea-php84) live on the server in
# shared/public.htaccess and are prepended to the release's public/.htaccess (ADR-049).
if [ -f "$BASE/shared/public.htaccess" ]; then
    { cat "$BASE/shared/public.htaccess"; echo; cat public/.htaccess; } > public/.htaccess.new && mv public/.htaccess.new public/.htaccess
fi

"$PHP" artisan storage:link --force
"$PHP" artisan migrate --force          # migrations are additive and reversible (07-QUALITY §4)
"$PHP" artisan db:seed --force          # EssentialSeeder only: idempotent, never overwrites edits
"$PHP" artisan optimize
"$PHP" artisan filament:optimize
"$PHP" artisan icons:cache

switch_to "$TARGET"
reload

# Keep the most recent releases for fast rollback.
ls -1t "$BASE/releases" | tail -n "+$((KEEP_RELEASES + 1))" | while read -r old; do rm -rf "$BASE/releases/$old"; done

echo "Release $TARGET is live."
