#!/bin/bash
set -euo pipefail

QUAY_URL="https://quay.url"
QUAY_FQDN="quay.url"

REPO="any-repo-name"
USERNAME="user"
PASSWORD="pass"
BLOB_FILE="blob.bin"

CHUNK_SIZE=$((20*1024*1024))   # 20 MB per chunk
TAIL_SIZE=$((10*1024*1024))   # send last 10 MB in final PUT
HEADERS_FILE="upload_headers.log"

# reset headers log
: > "$HEADERS_FILE"

# Create a dummy 50MB file if it doesn't exist
if [ ! -f "$BLOB_FILE" ]; then
  echo "Creating 50MB blob..."
  head -c 50M /dev/urandom > "$BLOB_FILE"
fi

FILE_SIZE=$(stat -c%s "$BLOB_FILE")
UPLOAD_LIMIT=$((FILE_SIZE - TAIL_SIZE))

# 1. Get a Bearer token
SCOPE="repository:${REPO}:push,pull"
BASE64=$(echo -ne $USERNAME:$PASSWORD | base64 -w 0)

TOKEN=$(curl -k -s -H "Authorization: Basic ${BASE64}" \
  "${QUAY_URL}/v2/auth?service=${QUAY_FQDN}&scope=${SCOPE}" | jq -r .token)

echo "Fetched Bearer token."

# 2. Start the upload (POST)
LOCATION=$(curl -vvvv -s -D - -o /dev/null \
  -H "Authorization: Bearer ${TOKEN}" \
  -X POST "${QUAY_URL}/v2/${REPO}/blobs/uploads/" \
  | tee -a "$HEADERS_FILE" \
  | grep -i Location: | awk '{print $2}' | tr -d '\r\n')

UPLOAD_URL="${LOCATION}"
echo "Upload location: $UPLOAD_URL"

# 3. Upload the blob in chunks except the last TAIL_SIZE
OFFSET=0
exec 3<"$BLOB_FILE"

while [ $OFFSET -lt $UPLOAD_LIMIT ]; do
  REMAIN=$((UPLOAD_LIMIT - OFFSET))
  SIZE=$(( REMAIN < CHUNK_SIZE ? REMAIN : CHUNK_SIZE ))
  END=$((OFFSET + SIZE - 1))

  RANGE_HEADER="Content-Range: ${OFFSET}-${END}"
  echo "Uploading chunk: offset=$OFFSET size=$SIZE (${RANGE_HEADER})"

  dd if=/dev/fd/3 bs=1 skip=$OFFSET count=$SIZE 2>/dev/null \
  | curl -vvvv -s -D - -o /dev/null \
      -H "Authorization: Bearer ${TOKEN}" \
      -H "Content-Type: application/octet-stream" \
      -H "${RANGE_HEADER}" \
      -X PATCH --data-binary @- "${UPLOAD_URL}" \
  | tee -a "$HEADERS_FILE" >/dev/null

  OFFSET=$((OFFSET + SIZE))
done

exec 3<&-
echo "Uploaded all but last $TAIL_SIZE bytes."

# 4. Finalize the upload (PUT + digest + last bytes)
DIGEST="sha256:$(sha256sum "${BLOB_FILE}" | awk '{print $1}')"
FINAL_URL="${UPLOAD_URL}?digest=${DIGEST}"
START=$UPLOAD_LIMIT
END=$((FILE_SIZE - 1))
RANGE_HEADER="Content-Range: ${START}-${END}"

echo "Finalizing upload with ${RANGE_HEADER} and digest ${DIGEST}"

dd if="${BLOB_FILE}" bs=1 skip=$UPLOAD_LIMIT count=$TAIL_SIZE 2>/dev/null \
| curl -vvvv -s -D - -o /dev/null \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/octet-stream" \
    -H "${RANGE_HEADER}" \
    -X PUT --data-binary @- "${FINAL_URL}" \
| tee -a "$HEADERS_FILE" >/dev/null

echo "Upload complete with digest ${DIGEST}"
echo "All headers logged in $HEADERS_FILE"
