#!/usr/bin/env bash
# Random photo from your Flickr photostream → Terminal Widget (--image --padding fill).
# Config: ~/.config/terminal-widget/flickr.env (see recipe).
#
# Usage:
#   flickr-random.sh [TARGET] [TAGS|-]
#
# TAGS: optional comma-separated Flickr tags to filter; "-" or omit for any photo.
#
# Strategy (see https://stackoverflow.com/a/62865365):
#   1) Fetch page 1 with per_page=1 to learn total/pages
#   2) Pick a random page in 1..min(pages, 4000)
#   3) Fetch that single photo with size URL extras
#
# Public photos only (api_key). Private photos need OAuth (not covered here).
# Tap refresh: set FLICKR_TAP_SHORTCUT (run-command is sandboxed).
set -euo pipefail

export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin${PATH:+:$PATH}"

FLICKR_ENV="${FLICKR_ENV:-$HOME/.config/terminal-widget/flickr.env}"
if [[ -f "$FLICKR_ENV" ]]; then
	# shellcheck source=/dev/null
	source "$FLICKR_ENV"
fi

if [[ -z "${TERMINAL_WIDGET:-}" ]]; then
	if [[ -x /opt/homebrew/bin/terminal-widget ]]; then
		TW=/opt/homebrew/bin/terminal-widget
	elif [[ -x /usr/local/bin/terminal-widget ]]; then
		TW=/usr/local/bin/terminal-widget
	else
		TW=terminal-widget
	fi
else
	TW="$TERMINAL_WIDGET"
fi

TARGET="${1:-${FLICKR_TARGET:-flickr}}"
TAGS_ARG="${2:-${FLICKR_TAGS:--}}"
[[ "$TAGS_ARG" == "-" ]] && TAGS_ARG=""

API_KEY="${FLICKR_API_KEY:-}"
USER_ID="${FLICKR_USER_ID:-}"
USERNAME="${FLICKR_USERNAME:-}"
# Flickr search/list soft-cap called out in the SO answer
MAX_PAGE="${FLICKR_MAX_PAGE:-4000}"

widget_error() {
	local msg="$1"
	echo "Flickr: $msg" >&2
	if command -v "$TW" >/dev/null 2>&1; then
		"$TW" --target "$TARGET" \
			--icon exclamationmark.triangle.fill \
			--background "#422006" \
			--foreground "#fde68a" \
			--text "Flickr: $msg" || true
	fi
}

if [[ -z "$API_KEY" ]]; then
	widget_error "FLICKR_API_KEY not set"
	exit 1
fi

for cmd in jq curl; do
	if ! command -v "$cmd" >/dev/null 2>&1; then
		widget_error "$cmd required"
		exit 1
	fi
done

if ! command -v "$TW" >/dev/null 2>&1; then
	widget_error "terminal-widget not found (set TERMINAL_WIDGET)"
	exit 1
fi

flickr_get() {
	# usage: flickr_get method key=val ...
	local method="$1"
	shift
	local url="https://api.flickr.com/services/rest/?method=${method}&api_key=${API_KEY}&format=json&nojsoncallback=1"
	local arg
	for arg in "$@"; do
		url+="&${arg}"
	done
	curl -fsS "$url"
}

# Resolve username / URL alias → NSID if needed.
# Flickr "username" (e.g. ttscoff) often differs from the photostream
# path alias (e.g. circlesixdesign). findByUsername only accepts the former;
# urls.lookupUser accepts a photostream URL.
if [[ -z "$USER_ID" && -n "$USERNAME" ]]; then
	LOOKUP=$(flickr_get flickr.people.findByUsername "username=$(printf %s "$USERNAME" | jq -sRr @uri)")
	USER_ID=$(echo "$LOOKUP" | jq -r '.user.nsid // empty')
	if [[ -z "$USER_ID" ]]; then
		PHOTO_URL="https://www.flickr.com/photos/${USERNAME}"
		LOOKUP=$(flickr_get flickr.urls.lookupUser "url=$(printf %s "$PHOTO_URL" | jq -sRr @uri)")
		USER_ID=$(echo "$LOOKUP" | jq -r '.user.id // empty')
	fi
	if [[ -z "$USER_ID" ]]; then
		ERR=$(echo "$LOOKUP" | jq -r '.message // "username/alias lookup failed"' 2>/dev/null || echo "username/alias lookup failed")
		widget_error "$ERR"
		exit 1
	fi
fi

if [[ -z "$USER_ID" ]]; then
	widget_error "set FLICKR_USER_ID or FLICKR_USERNAME"
	exit 1
fi

USER_Q="user_id=$(printf %s "$USER_ID" | jq -sRr @uri)"
EXTRAS="extras=url_o,url_l,url_c,url_z,url_m,url_n,media"
COMMON=("$USER_Q" "media=photos" "$EXTRAS")

if [[ -n "$TAGS_ARG" ]]; then
	# Tag filter via search (still scoped to this user)
	METHOD_COUNT=flickr.photos.search
	METHOD_PAGE=flickr.photos.search
	TAG_Q="tags=$(printf %s "$TAGS_ARG" | jq -sRr @uri)"
	COMMON+=("$TAG_Q" "tag_mode=all")
else
	METHOD_COUNT=flickr.people.getPublicPhotos
	METHOD_PAGE=flickr.people.getPublicPhotos
fi

COUNT_JSON=$(flickr_get "$METHOD_COUNT" "${COMMON[@]}" "per_page=1" "page=1") || {
	widget_error "API request failed"
	exit 1
}

STAT=$(echo "$COUNT_JSON" | jq -r '.stat // empty')
if [[ "$STAT" != "ok" ]]; then
	ERR=$(echo "$COUNT_JSON" | jq -r '.message // "API error"' 2>/dev/null || echo "API error")
	widget_error "$ERR"
	exit 1
fi

TOTAL=$(echo "$COUNT_JSON" | jq -r '.photos.total // 0' | tr -d ',')
PAGES=$(echo "$COUNT_JSON" | jq -r '.photos.pages // 0')
if [[ "${TOTAL:-0}" -lt 1 || "${PAGES:-0}" -lt 1 ]]; then
	widget_error "no photos found"
	exit 1
fi

# Cap pages so random page stays in a range Flickr actually returns uniquely
if [[ "$PAGES" -gt "$MAX_PAGE" ]]; then
	PAGES="$MAX_PAGE"
fi

RAND_PAGE=$(( (RANDOM % PAGES) + 1 ))
# Prefer a fuller random when available
if command -v od >/dev/null 2>&1; then
	RAND_PAGE=$(( ($(od -An -N2 -tu2 </dev/urandom | tr -d ' ') % PAGES) + 1 ))
fi

PAGE_JSON=$(flickr_get "$METHOD_PAGE" "${COMMON[@]}" "per_page=1" "page=${RAND_PAGE}") || {
	widget_error "API request failed"
	exit 1
}

STAT=$(echo "$PAGE_JSON" | jq -r '.stat // empty')
if [[ "$STAT" != "ok" ]]; then
	ERR=$(echo "$PAGE_JSON" | jq -r '.message // "API error"' 2>/dev/null || echo "API error")
	widget_error "$ERR"
	exit 1
fi

# Prefer larger sizes; url_o may be missing without original download perms
IMAGE_URL=$(echo "$PAGE_JSON" | jq -r '
	.photos.photo[0] as $p
	| ($p.url_l // $p.url_c // $p.url_z // $p.url_o // $p.url_m // $p.url_n // empty)
')

if [[ -z "$IMAGE_URL" || "$IMAGE_URL" == "null" ]]; then
	widget_error "no image URL on page ${RAND_PAGE}"
	exit 1
fi

ACTION_ARGS=()
if [[ -n "${FLICKR_TAP_SHORTCUT:-}" ]]; then
	ACTION_ARGS=(--action-kind run-shortcut --action-value "$FLICKR_TAP_SHORTCUT")
fi

"$TW" \
	--target "$TARGET" \
	--image "$IMAGE_URL" \
	--padding fill \
	"${ACTION_ARGS[@]}"