#!/usr/bin/env bash
# Convert one 2D video to full side-by-side 3D with the Owl3D API.
# Needs: bash, curl, jq, ffprobe.
# Usage: OWL3D_API_KEY=o3d_live_... bash convert.sh my-video.mp4
set -euo pipefail
: "${OWL3D_API_KEY:?set OWL3D_API_KEY}"
API="${OWL3D_API_URL:-https://api.owl3d.com}"
FILE="$1"
auth=(-H "Authorization: Bearer $OWL3D_API_KEY")
json=(-H "Content-Type: application/json")

# 1. Read the facts of the file and make the fingerprint.
SIZE=$(stat -f%z "$FILE" 2>/dev/null || stat -c%s "$FILE")
EDGE=$(( SIZE < 4194304 ? SIZE : 4194304 ))
HEAD=$(head -c "$EDGE" "$FILE" | shasum -a 256 | cut -d" " -f1)
TAIL=$(tail -c "$EDGE" "$FILE" | shasum -a 256 | cut -d" " -f1)
P=$(ffprobe -v error -print_format json -show_streams -show_format "$FILE")
BODY=$(jq -n --argjson p "$P" --arg name "$(basename "$FILE")" --argjson size "$SIZE" \
  --arg head "$HEAD" --arg tail "$TAIL" --argjson edge "$EDGE" '
  ($p.streams | map(select(.codec_type=="video"))[0]) as $v |
  ($v.avg_frame_rate | split("/") | map(tonumber)) as $f |
  {name:$name, size:$size, durationSeconds:($p.format.duration|tonumber),
   width:$v.width, height:$v.height, fps:(if $f[1]>0 then $f[0]/$f[1] else $f[0] end),
   codec:({h264:"H.264",hevc:"HEVC",av1:"AV1",vp9:"VP9"}[$v.codec_name] // $v.codec_name),
   bitDepth:(if ($v.pix_fmt|test("10")) then 10 else 8 end), chroma:"4:2:0",
   fingerprint:{size:$size, headSha256:$head, tailSha256:$tail, edgeBytes:$edge}}')

# 2. Estimate. Nothing is charged.
EST=$(curl -s -X POST "$API/v1/estimates" "${auth[@]}" "${json[@]}" -d "$BODY")
[ "$(echo "$EST" | jq -r .ok)" = true ] || { echo "estimate refused: $EST"; exit 1; }
echo "price: $(echo "$EST" | jq -r .credits.total) credits"

# 3. Create the job. This reserves the credits.
JOB=$(curl -s -X POST "$API/v1/jobs" "${auth[@]}" "${json[@]}" \
  -d "$(jq -n --arg id "$(echo "$EST" | jq -r .id)" '{estimateId:$id}')")
ID=$(echo "$JOB" | jq -r .id)
[ "$ID" != null ] || { echo "create refused: $JOB"; exit 1; }
PART=$(echo "$JOB" | jq -r .upload.partSize)

# 4. Upload each part, keep each ETag, then complete.
TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT
split -b "$PART" "$FILE" "$TMP/part_"
ETAGS=()
i=0
for f in "$TMP"/part_*; do
  URL=$(echo "$JOB" | jq -r ".upload.parts[$i]")
  ETAG=$(curl -s -f -D - -o /dev/null --upload-file "$f" "$URL" | tr -d '\r' | awk 'tolower($1)=="etag:"{print $2}')
  ETAGS+=("$ETAG")
  i=$((i+1))
done
curl -s -X POST "$API/v1/jobs/$ID/upload-complete" "${auth[@]}" "${json[@]}" \
  -d "$(printf '%s\n' "${ETAGS[@]}" | jq -R . | jq -s '{etags:.}')" | jq -c .

# 5. Poll every 15 s until the job ends.
while :; do
  ST=$(curl -s "$API/v1/jobs/$ID" "${auth[@]}")
  S=$(echo "$ST" | jq -r .status)
  echo "$S $(echo "$ST" | jq -r '.progress // 0')"
  case "$S" in
    done) break;;
    failed|cancelled) echo "$ST"; exit 1;;
    insufficient_credits) echo "$ST" | jq -r '"add \(.shortBy) credits, then POST \(.resumeUrl) before \(.deleteAt)"'; exit 1;;
  esac
  sleep 15
done

# 6. Get the link (15 min, GET only) and download.
RES=$(curl -s "$API/v1/jobs/$ID/result" "${auth[@]}")
OUT=$(echo "$RES" | jq -r .filename)
curl -s -f -L -o "$OUT" "$(echo "$RES" | jq -r .url)"
echo "saved $OUT"
