#!/usr/bin/env bash

set -Eeuo pipefail

# Deploy the already-checked-out desxpert-api revision.
# GitHub Actions should run `git pull --ff-only` before invoking this script.

DEPLOY_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEPLOY_API_DIR="$(cd "$DEPLOY_SCRIPT_DIR/.." && pwd)"
DEPLOY_PHP_BIN="${DEPLOY_PHP_BIN:-php}"
DEPLOY_COMPOSER_BIN="${DEPLOY_COMPOSER_BIN:-composer}"
DEPLOY_NPM_BIN="${DEPLOY_NPM_BIN:-npm}"
DEPLOY_HEALTHCHECK_URL="${DEPLOY_HEALTHCHECK_URL:-}"
DEPLOY_API_DOWN=0

deployment_cleanup() {
    local exit_code=$?
    trap - EXIT

    if [[ "$DEPLOY_API_DOWN" -eq 1 ]]; then
        echo "Bringing the API back online..."
        cd "$DEPLOY_API_DIR"
        "$DEPLOY_PHP_BIN" artisan up || true
    fi

    if [[ "$exit_code" -ne 0 ]]; then
        echo "Deployment failed with exit code $exit_code." >&2
    fi

    exit "$exit_code"
}

trap deployment_cleanup EXIT

require_command() {
    if ! command -v "$1" >/dev/null 2>&1; then
        echo "Required command is not installed: $1" >&2
        exit 1
    fi
}

require_command "$DEPLOY_PHP_BIN"
require_command "$DEPLOY_COMPOSER_BIN"
require_command "$DEPLOY_NPM_BIN"

cd "$DEPLOY_API_DIR"

if [[ ! -f artisan || ! -f composer.json ]]; then
    echo "The deployment directory is not a valid Laravel application: $DEPLOY_API_DIR" >&2
    exit 1
fi

if [[ ! -f .env ]]; then
    echo "Missing production environment file: $DEPLOY_API_DIR/.env" >&2
    exit 1
fi

DEPLOY_REVISION="unknown"
if command -v git >/dev/null 2>&1 && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
    DEPLOY_REVISION="$(git rev-parse --short HEAD)"
fi

echo "Deploying desxpert-api revision $DEPLOY_REVISION from $DEPLOY_API_DIR"

echo "Enabling maintenance mode..."
"$DEPLOY_PHP_BIN" artisan down --retry=60
DEPLOY_API_DOWN=1

echo "Installing production PHP dependencies..."
"$DEPLOY_COMPOSER_BIN" install \
    --no-dev \
    --prefer-dist \
    --no-interaction \
    --no-progress \
    --optimize-autoloader

echo "Installing frontend dependencies..."
if [[ -f package-lock.json ]]; then
    "$DEPLOY_NPM_BIN" ci --no-audit --no-fund
else
    echo "package-lock.json is missing; using npm install. Commit a lock file for reproducible deployments."
    "$DEPLOY_NPM_BIN" install --no-audit --no-fund --package-lock=false
fi

echo "Building production assets..."
"$DEPLOY_NPM_BIN" run build

echo "Clearing stale Laravel caches..."
"$DEPLOY_PHP_BIN" artisan optimize:clear

echo "Running database migrations..."
"$DEPLOY_PHP_BIN" artisan migrate --force --isolated

if [[ ! -e public/storage ]]; then
    echo "Creating the public storage link..."
    "$DEPLOY_PHP_BIN" artisan storage:link
fi

echo "Caching Laravel configuration, routes, events, and views..."
"$DEPLOY_PHP_BIN" artisan optimize

echo "Gracefully restarting queue workers..."
"$DEPLOY_PHP_BIN" artisan queue:restart

echo "Disabling maintenance mode..."
"$DEPLOY_PHP_BIN" artisan up
DEPLOY_API_DOWN=0

if [[ -n "$DEPLOY_HEALTHCHECK_URL" ]]; then
    require_command curl
    echo "Checking $DEPLOY_HEALTHCHECK_URL..."
    curl --fail --silent --show-error --retry 3 --retry-delay 2 "$DEPLOY_HEALTHCHECK_URL" >/dev/null
fi

echo "desxpert-api revision $DEPLOY_REVISION deployed successfully."
