#!/usr/bin/env bash
IFS=$'\n\t'
set -euo pipefail

#
# GovCMS database sync.
#
# This will pull a database from the production environment.
#

LAGOON_ENVIRONMENT_TYPE=${LAGOON_ENVIRONMENT_TYPE:-production}
GOVCMS_SKIP_DB_SYNC=${GOVCMS_SKIP_DB_SYNC:-FALSE}
GOVCMS_CACHE_REBUILD_BEFORE_DB_SYNC=${GOVCMS_CACHE_REBUILD_BEFORE_DB_SYNC:-FALSE}
GOVCMS_DEPLOY_WORKFLOW_CONTENT=${GOVCMS_DEPLOY_WORKFLOW_CONTENT:-retain}
GOVCMS_SITE_ALIAS=${GOVCMS_SITE_ALIAS:-govcms.prod}
GOVCMS_SITE_ALIAS_PATH=${GOVCMS_SITE_ALIAS_PATH:-/app/drush/sites}
MARIADB_READREPLICA_HOSTS=${MARIADB_READREPLICA_HOSTS:-}
GOVCMS_TEST_CANARY=${GOVCMS_TEST_CANARY:-FALSE}
LAGOON_GIT_SAFE_BRANCH=${LAGOON_GIT_SAFE_BRANCH:-master}

# For some projects with huge database sizes, the drush command might fail
# due to the hardcoded drush timeout of 4 hours. If that happens, we have the
# ability to set this variable to load the database via mysql directly,
# thereby avoiding the drush timeout.
DB_LOAD_NO_DRUSH=${DB_LOAD_NO_DRUSH:-FALSE}

# Drush 12 support.
DRUSH="${GOVCMS_DRUSH:-none}"
if [ "$DRUSH" == "none" ]; then
  DRUSH=$(which /app/vendor/bin/drush > /dev/null 2>&1 && echo "/app/vendor/bin/drush" || echo "/usr/local/bin/drush")
fi

echo "GovCMS Deploy :: Database synchronisation"

if [[ "$GOVCMS_SKIP_DB_SYNC" != FALSE ]]; then
  echo "[skip]: Workflow is not set to sync db."
  exit 0
fi

if [ "$LAGOON_ENVIRONMENT_TYPE" = "production" ]; then
  echo "[skip]: Production environment can't be synced."
  exit 0
fi

echo "[info]: Environment type: $LAGOON_ENVIRONMENT_TYPE"
echo "[info]: Content strategy: $GOVCMS_DEPLOY_WORKFLOW_CONTENT"
echo "[info]: Site alias:       $GOVCMS_SITE_ALIAS"
echo "[info]: Alias path:       $GOVCMS_SITE_ALIAS_PATH"

echo "[info]: Check that the site can be bootstrapped."

if [[ "$GOVCMS_CACHE_REBUILD_BEFORE_DB_SYNC" = TRUE ]]; then
  echo "[info]: Rebuilding cache before database sync."
  "$DRUSH" cr
fi
STATUS=$("$DRUSH" status --fields=bootstrap --format=json)

if [[ "$GOVCMS_TEST_CANARY" = TRUE ]]; then
  echo "[info]: Canary site... syncing."
elif [[ "$LAGOON_GIT_SAFE_BRANCH" = internal-govcms-update* ]]; then
  echo "[info]: Upgrade branch... syncing."
elif [ "$(jq -r '.bootstrap' 2> /dev/null <<< "$STATUS")" != "Successful" ]; then
  # This will ensure that the database is synchronised on the first deploy
  # of an environment in Lagoon.
  echo "[info]: Site could not be bootstrapped... syncing."
elif [ "$GOVCMS_DEPLOY_WORKFLOW_CONTENT" != "import" ]; then
  # Allow per environment overrides for the synchronisation flow: if the site
  # has bootstrapped but the environment is not set to "import" for the workflow
  # then we will not synchronise the database.
  echo "[skip]: Site can be bootstrapped and the content workflow is not set to \"import\"."
  exit 0
fi

echo "[info]: Preparing database sync"

# shellcheck disable=SC2086
"$DRUSH" --alias-path="$GOVCMS_SITE_ALIAS_PATH" @"$GOVCMS_SITE_ALIAS" sql:dump \
  --gzip --extra-dump=--no-tablespaces --structure-tables-list=search_index,search_total,redirect_404,cache,cache_* --result-file=/tmp/sync.sql \
  --skip-tables-key=common -y
"$DRUSH" rsync --alias-path="$GOVCMS_SITE_ALIAS_PATH" @"$GOVCMS_SITE_ALIAS":/tmp/sync.sql.gz /tmp/ -y

if [[ "$DB_LOAD_NO_DRUSH" = TRUE ]]; then
  DB_CONF=$("$DRUSH" sql:conf --show-passwords --format=json 2>&1)
  DB_NAME=$(echo "$DB_CONF" | jq -r '.database')
  DB_HOST=$(echo "$DB_CONF" | jq -r '.host')
  DB_PORT=$(echo "$DB_CONF" | jq -r '.port')
  DB_USER=$(echo "$DB_CONF" | jq -r '.username')
  DB_PASS=$(echo "$DB_CONF" | jq -r '.password')

  LOAD_TMP_FILE=$(mktemp -u --suffix=.govcms-db-load)
  cat > "$LOAD_TMP_FILE" << EOF
[client]
user=${DB_USER}
password=${DB_PASS}
EOF

  echo "[info]: Loading database using mysql"
  gunzip < /tmp/sync.sql.gz | mysql --defaults-file="$LOAD_TMP_FILE" \
    --host="$DB_HOST" --port="$DB_PORT" "$DB_NAME"
else
  echo "[info]: Loading database using drush"
  gunzip < /tmp/sync.sql.gz | "$DRUSH" sqlc
fi

rm /tmp/sync.sql.gz
# @todo: Add sanitisation?

echo "[success]: Completed successfully."
