#!/usr/bin/env bash
# OpenAI GPT Image → Terminal Widget (--image).
# Config: ~/.config/terminal-widget/openai.env (see recipe).
#
# Usage:
#   openai-image.sh [TARGET] [PROMPT|-] [SIZE]
#
# SIZE: square | landscape | portrait | or WxH (e.g. 1024x1024)
# PROMPT: subject/theme, or "-" to use OPENAI_IMAGE_PROMPT / a surprise default.
#
# Duplicate a LaunchAgent and change TARGET + PROMPT for multiple widgets.
# Prefer long intervals (hours/days) — each run is a paid API call.
#
# Tap refresh: set OPENAI_TAP_SHORTCUT in openai.env (run-command is sandboxed).
set -euo pipefail

export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin${PATH:+:$PATH}"

OPENAI_ENV="${OPENAI_ENV:-$HOME/.config/terminal-widget/openai.env}"
if [[ -f "$OPENAI_ENV" ]]; then
	# shellcheck source=/dev/null
	source "$OPENAI_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:-${OPENAI_IMAGE_TARGET:-openai-image}}"
PROMPT_ARG="${2:-${OPENAI_IMAGE_PROMPT:--}}"
SIZE_ARG="${3:-${OPENAI_IMAGE_SIZE:-square}}"
[[ "$PROMPT_ARG" == "-" ]] && PROMPT_ARG=""

MODEL="${OPENAI_IMAGE_MODEL:-gpt-image-1-mini}"
QUALITY="${OPENAI_IMAGE_QUALITY:-low}"
API_KEY="${OPENAI_API_KEY:-}"

case "$SIZE_ARG" in
	square | s) SIZE="1024x1024" ;;
	landscape | l) SIZE="1536x1024" ;;
	portrait | p) SIZE="1024x1536" ;;
	*) SIZE="$SIZE_ARG" ;;
esac

if [[ -n "$PROMPT_ARG" ]]; then
	if [[ "${OPENAI_IMAGE_PROMPT_MODE:-theme}" == "raw" ]]; then
		PROMPT="$PROMPT_ARG"
	else
		PREFIX="${OPENAI_IMAGE_PROMPT_PREFIX:-A striking wallpaper-style image of}"
		PROMPT="${PREFIX} ${PROMPT_ARG}, vivid but clean composition, no text or watermarks, suitable as a desktop widget background."
	fi
else
	PROMPT="${OPENAI_IMAGE_DEFAULT_PROMPT:-A surprising, beautiful wallpaper-style scene with vivid color and strong composition, no text or watermarks, suitable as a desktop widget background. Subject chosen creatively.}"
fi

widget_error() {
	local msg="$1"
	echo "OpenAI Image: $msg" >&2
	if command -v "$TW" >/dev/null 2>&1; then
		"$TW" --target "$TARGET" \
			--icon exclamationmark.triangle.fill \
			--background "#422006" \
			--foreground "#fde68a" \
			--text "OpenAI: $msg" || true
	fi
}

if [[ -z "$API_KEY" ]]; then
	widget_error "OPENAI_API_KEY not set"
	exit 1
fi

for cmd in jq curl base64; 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

CACHE_DIR="${WIDGET_CACHE_DIR:-$HOME/.cache/terminal-widget}"
mkdir -p "$CACHE_DIR"
OUT_PNG="${CACHE_DIR}/openai-image-${TARGET}.png"
BODY=$(jq -n \
	--arg model "$MODEL" \
	--arg prompt "$PROMPT" \
	--arg size "$SIZE" \
	--arg quality "$QUALITY" \
	'{model:$model, prompt:$prompt, size:$size, quality:$quality}')

HTTP_CODE=0
RESP_FILE=$(mktemp)
trap 'rm -f "$RESP_FILE"' EXIT

HTTP_CODE=$(curl -sS -o "$RESP_FILE" -w '%{http_code}' \
	-X POST "https://api.openai.com/v1/images/generations" \
	-H "Authorization: Bearer ${API_KEY}" \
	-H "Content-Type: application/json" \
	-d "$BODY") || true

if [[ "$HTTP_CODE" != "200" ]]; then
	ERR=$(jq -r '.error.message // .error.code // "API request failed"' "$RESP_FILE" 2>/dev/null || echo "HTTP $HTTP_CODE")
	widget_error "$ERR"
	exit 1
fi

B64=$(jq -r '.data[0].b64_json // empty' "$RESP_FILE")
if [[ -z "$B64" || "$B64" == "null" ]]; then
	widget_error "no image in response"
	exit 1
fi

if ! printf '%s' "$B64" | base64 --decode >"$OUT_PNG"; then
	widget_error "failed to decode image"
	exit 1
fi

ACTION_ARGS=()
if [[ -n "${OPENAI_TAP_SHORTCUT:-}" ]]; then
	ACTION_ARGS=(--action-kind run-shortcut --action-value "$OPENAI_TAP_SHORTCUT")
fi

"$TW" \
	--target "$TARGET" \
	--image "$OUT_PNG" \
	--padding fill \
	"${ACTION_ARGS[@]}"