#!/bin/sh
set -eu

file=${1:?Usage: sh share-file.sh FILE [MIME_TYPE]}
content_type=${2:-application/octet-stream}

if [ ! -f "$file" ] || [ ! -r "$file" ]; then
    printf 'Cannot read file: %s\n' "$file" >&2
    exit 1
fi

work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM

request() {
    stage=$1
    output=$2
    shift 2

    if ! status=$(curl --fail-with-body --silent --show-error \
        --connect-timeout 10 --max-time 60 \
        --retry 2 --retry-delay 1 --retry-max-time 180 \
        --output "$output" --write-out '%{http_code}' "$@"); then
        printf '%s failed (HTTP %s).\n' "$stage" "${status:-unknown}" >&2
        head -c 500 "$output" >&2
        printf '\n' >&2
        return 1
    fi

    case "$status" in
        2??) return 0 ;;
        *) printf '%s returned unexpected HTTP %s.\n' "$stage" "$status" >&2; return 1 ;;
    esac
}

size=$(wc -c < "$file" | tr -d ' ')
jq -n --arg filename "$(basename "$file")" --arg contentType "$content_type" \
    --argjson size "$size" '{filename: $filename, contentType: $contentType, size: $size}' \
    > "$work/request.json"

request Presign "$work/signed.json" https://yoink.zip/api/v1/presign \
    --header 'Content-Type: application/json' --data-binary "@$work/request.json"

upload_url=$(jq -er '.uploadUrl | strings | select(startswith("https://"))' "$work/signed.json")
upload_type=$(jq -er '.contentType | strings | select(length > 0)' "$work/signed.json")
public_url=$(jq -er '.publicUrl | strings | select(startswith("https://files.yoink.zip/"))' "$work/signed.json")

request Upload "$work/upload-response.txt" --request PUT "$upload_url" \
    --header "Content-Type: $upload_type" --data-binary "@$file"

printf '%s\n' "$public_url"
