#!/bin/bash
#
# Deploys the Underwear Considered site to Cloudflare Pages.
#
# Written for an unreliable connection. Cloudflare stores uploaded files by
# their contents, so a deploy that dies halfway has still banked everything
# it managed to send. Running it again skips all of that and carries on from
# where it stopped. This script simply does that for you, over and over,
# until the whole site is up.
#
# It also writes everything it does to deploy-log.txt next to itself, so if
# it goes wrong there is a file to send on rather than a terminal window to
# transcribe.
#

cd "$(dirname "$0")" || exit 1

# Everything from here down goes to the screen and to the log at once.
if [ -z "$UC_LOGGING" ]; then
  export UC_LOGGING=1
  rm -f deploy-log.txt
  exec > >(tee deploy-log.txt) 2>&1
fi

# Not pinned to a version on purpose. The two commands used below have been
# stable across every major release of this tool, whereas pinning an old one
# risks it refusing to start on a newly installed Node.
WRANGLER="wrangler@latest"
SAVED=".cloudflare-project"
HOLD=".og-held-back"
TRIES=12

echo ""
echo "  Underwear Considered"
echo "  Deploy to Cloudflare Pages"
echo "  ------------------------------------------------"
echo "  Started at $(date)"
echo ""

# If a previous run was closed midway through the two-stage upload below, the
# social images will still be parked outside the site folder. Put them back
# before doing anything else so the site is always whole on disk.
if [ -d "$HOLD" ]; then
  mv "$HOLD" "site/og"
  echo "  (restored the social images from an interrupted run)"
  echo ""
fi

if [ ! -f "site/index.html" ]; then
  echo "  I cannot find the site folder."
  echo ""
  echo "  This script and the folder called 'site' need to stay together in"
  echo "  the same place. Move them back and double-click this again."
  echo ""
  read -n 1 -s -r -p "  Press any key to close. "
  echo ""
  exit 1
fi

if ! command -v node >/dev/null 2>&1; then
  echo "  Node is not installed on this Mac, and Cloudflare's deploy tool"
  echo "  needs it to run."
  echo ""
  echo "      1. Go to   https://nodejs.org"
  echo "      2. Download the big green LTS button"
  echo "      3. Open the file it downloads and click through the installer"
  echo "      4. Come back here and double-click this file again"
  echo ""
  read -n 1 -s -r -p "  Press any key to close. "
  echo ""
  exit 1
fi

FIRST_RUN=0
if [ -f "$SAVED" ]; then
  PROJECT="$(cat "$SAVED")"
  echo "  Deploying to project:  $PROJECT"
  echo ""
else
  FIRST_RUN=1
  echo "  Fetching your Cloudflare projects. If a browser window opens"
  echo "  asking you to log in, say yes. It only happens once."
  echo ""
  read -n 1 -s -r -p "  Press any key to start. "
  echo ""
  echo ""

  npx --yes "$WRANGLER" pages project list
  echo ""
  echo "  Type the name of your project exactly as it appears in the first"
  echo "  column above, then press return."
  echo ""
  read -r -p "  Project name: " PROJECT
  PROJECT="$(echo "$PROJECT" | tr -d '[:space:]')"
  echo ""

  if [ -z "$PROJECT" ]; then
    echo "  No name typed, so nothing has been deployed."
    echo ""
    read -n 1 -s -r -p "  Press any key to close. "
    echo ""
    exit 1
  fi
fi

#
# One upload attempt, repeated until it works or we run out of patience.
# The timings are printed because they are the only measurement of the
# connection we are ever going to get, and a run that dies after four
# seconds means something very different to one that dies after four
# minutes.
#
deploy_pass () {
  local label="$1"
  local n=1
  local t0 t1 rc

  while [ $n -le $TRIES ]; do
    echo ""
    echo "  ------------------------------------------------"
    echo "  $label, attempt $n of $TRIES"
    echo "  ------------------------------------------------"
    echo ""

    t0=$(date +%s)
    npx --yes "$WRANGLER" pages deploy ./site --project-name="$PROJECT"
    rc=$?
    t1=$(date +%s)

    echo ""
    echo "  Attempt $n finished after $((t1 - t0)) seconds, exit code $rc."

    if [ $rc -eq 0 ]; then
      echo "  That one worked."
      return 0
    fi

    if [ $n -lt $TRIES ]; then
      echo "  Failed. Everything it managed to send is kept by Cloudflare,"
      echo "  so the next attempt starts further along than this one did."
      echo "  Waiting fifteen seconds."
      sleep 15
    fi

    n=$((n + 1))
  done

  return 1
}

#
# Two stages, on purpose.
#
# The social preview images are a third of the files and most of the weight,
# and they are the least important thing here: they are the picture that
# appears when someone pastes a link into a group chat, and nothing a reader
# of the site ever sees. So the site goes up without them first. If the
# connection gives out before the second stage finishes, the site is still
# live and working, and the only casualty is the thumbnail on shared links.
#
echo ""
echo "  This runs in two stages. Stage one puts the site up. Stage two adds"
echo "  the social preview images. If stage two never finishes, the site is"
echo "  live regardless, so leave it running and go and do something else."

mv "site/og" "$HOLD"
deploy_pass "Stage one of two, the site itself"
STAGE1=$?
mv "$HOLD" "site/og"

if [ $STAGE1 -ne 0 ]; then
  echo ""
  echo "  ================================================"
  echo "  Stage one did not get through after $TRIES attempts."
  echo "  ================================================"
  echo ""
  echo "  There is a file called deploy-log.txt sitting next to this script."
  echo "  Send that to Claude. It has every error in it."
  echo ""
  read -n 1 -s -r -p "  Press any key to close. "
  echo ""
  exit 1
fi

if [ $FIRST_RUN -eq 1 ]; then
  echo "$PROJECT" > "$SAVED"
fi

echo ""
echo "  ================================================"
echo "  The site is live."
echo "  ================================================"
echo ""
echo "  Stage two now adds the social preview images. This part is optional."
echo "  Closing the window will not undo anything above."
echo ""

deploy_pass "Stage two of two, the social images"
STAGE2=$?

echo ""
if [ $STAGE2 -eq 0 ]; then
  echo "  ================================================"
  echo "  All done. Everything is up."
  echo "  ================================================"
else
  echo "  Stage two did not finish, which is not a problem worth worrying"
  echo "  about. Your site is live and complete. Shared links will show the"
  echo "  title and description without a picture until this gets through."
  echo ""
  echo "  Double-clicking this again later will pick up where it left off."
fi

echo ""
echo "  Finished at $(date)"
echo "  A full record of this run is in deploy-log.txt next to this script."
echo ""
read -n 1 -s -r -p "  Press any key to close. "
echo ""
