#!/usr/bin/env bash

set -euo pipefail

repository_dir="${BYTELIFT_INTERACTIVES_REPOSITORY_DIR:-/srv/bytelift-interactives/repo}"
releases_dir="${BYTELIFT_INTERACTIVES_RELEASES_DIR:-/var/www/bytelift-interactives/releases}"
current_link="${BYTELIFT_INTERACTIVES_CURRENT_LINK:-/var/www/interactives}"
smoke_origin="${BYTELIFT_INTERACTIVES_SMOKE_ORIGIN:-https://bytelift.ph}"
commit_ref="${1:-}"
stage_root=""

cleanup() {
  if [[ -n "$stage_root" && -d "$stage_root" && "$stage_root" == "$releases_dir"/.stage.* ]]; then
    rm -rf -- "$stage_root"
  fi
}

restore_previous_release() {
  local previous_target="$1"
  local next_link="${current_link}.new"

  if [[ -n "$previous_target" && -d "$previous_target" ]]; then
    unlink "$next_link" 2>/dev/null || true
    ln -s "$previous_target" "$next_link"
    mv -Tf "$next_link" "$current_link"
  elif [[ -L "$current_link" ]]; then
    unlink "$current_link"
  fi
}

prune_old_releases() {
  local active_release
  local release_path
  local release_name
  local retained=0

  active_release="$(readlink -f "$current_link")"

  while IFS= read -r release_path; do
    release_name="$(basename "$release_path")"
    [[ "$release_name" =~ ^[0-9a-f]{40}$ ]] || continue

    retained=$((retained + 1))
    if (( retained > 3 )) && [[ "$release_path" != "$active_release" ]]; then
      rm -rf -- "$release_path"
    fi
  done < <(find "$releases_dir" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %p\n' | sort -nr | cut -d' ' -f2-)
}

trap cleanup EXIT

if (( EUID != 0 )); then
  echo "Run this deployment script as root." >&2
  exit 77
fi

if [[ -z "$commit_ref" ]]; then
  echo "Usage: $0 COMMIT_SHA" >&2
  exit 64
fi

if [[ ! -d "$repository_dir/.git" ]]; then
  echo "Repository not found: $repository_dir" >&2
  exit 66
fi

git -C "$repository_dir" fetch --prune origin master
commit_sha="$(git -C "$repository_dir" rev-parse --verify "${commit_ref}^{commit}")"

if ! git -C "$repository_dir" merge-base --is-ancestor "$commit_sha" origin/master; then
  echo "Commit is not reachable from origin/master: $commit_sha" >&2
  exit 65
fi

install -d -m 0755 "$releases_dir"
release_dir="$releases_dir/$commit_sha"

if [[ ! -d "$release_dir" ]]; then
  stage_root="$(mktemp -d "$releases_dir/.stage.XXXXXX")"
  source_tree="$stage_root/source"
  release_tree="$stage_root/release"
  install -d -m 0755 "$source_tree"

  git -C "$repository_dir" archive "$commit_sha" | tar -x -C "$source_tree"
  "$source_tree/scripts/build_release.sh" "$source_tree" "$release_tree"
  chown -R root:www-data "$release_tree"
  mv "$release_tree" "$release_dir"
fi

previous_target="$(readlink -f "$current_link" 2>/dev/null || true)"
next_link="${current_link}.new"

if [[ -e "$next_link" || -L "$next_link" ]]; then
  echo "Temporary link path already exists: $next_link" >&2
  exit 73
fi

ln -s "$release_dir" "$next_link"
mv -Tf "$next_link" "$current_link"

if ! curl --fail --silent --show-error --location --output /dev/null \
  "$smoke_origin/interactives/adventure_time/"; then
  restore_previous_release "$previous_target"
  echo "Game smoke test failed; restored the previous release." >&2
  exit 1
fi

if ! curl --fail --silent --show-error --location --output /dev/null \
  "$smoke_origin/interactives/connection/env.js"; then
  restore_previous_release "$previous_target"
  echo "Connection helper smoke test failed; restored the previous release." >&2
  exit 1
fi

prune_old_releases
echo "Deployed ByteLift interactives release $commit_sha"
