#!/usr/bin/env bash
# AppFigures daily downloads and revenue → Terminal Widget.
# Run once per day (cron/launchd). Requires dashboard.env (see recipe instructions).
set -euo pipefail

# --- Config ---
DASHBOARD_ENV="${DASHBOARD_ENV:-$HOME/.config/terminal-widget/dashboard.env}"
if [[ -f "$DASHBOARD_ENV" ]]; then
	# shellcheck source=/dev/null
	source "$DASHBOARD_ENV"
fi

API_BASE="${APPFIGURES_API_BASE:-https://api.appfigures.com/v2}"
TOKEN="${APPFIGURES_ACCESS_TOKEN:-${APPFIGURES_TOKEN:-}}"
CACHE_DIR="${WIDGET_CACHE_DIR:-$HOME/.cache/terminal-widget}"
CACHE_JSON="$CACHE_DIR/appfigures-sales.json"
CACHE_STAMP="$CACHE_DIR/appfigures-sales.fetched_on"
daily_tsv="$CACHE_DIR/appfigures-daily.tsv"
TABLE_TARGET="${APPFIGURES_TABLE_TARGET:-appfigures-table}"
DL_CHART_TARGET="${APPFIGURES_DL_CHART_TARGET:-appfigures-downloads}"
REV_CHART_TARGET="${APPFIGURES_REV_CHART_TARGET:-appfigures-revenue}"
TABLE_LABEL="${APPFIGURES_TABLE_LABEL:-App Store Sales}"
TW="${TERMINAL_WIDGET:-terminal-widget}"
DAYS_TABLE="${APPFIGURES_TABLE_DAYS:-7}"
DAYS_CHART="${APPFIGURES_CHART_DAYS:-14}"

mkdir -p "$CACHE_DIR"

# --- Helpers ---
format_usd() {
	local amount="${1:-0}"
	printf '$%s' "$(
		awk -v n="$amount" 'BEGIN {
			neg = (n < 0)
			if (neg) n = -n
			s = sprintf("%.0f", n + 0)
			out = ""
			len = length(s)
			for (i = len; i >= 1; i--) {
				out = substr(s, i, 1) out
				if ((len - i + 1) % 3 == 0 && i > 1) out = "," out
			}
			if (neg) out = "-" out
			print out
		}'
	)"
}

format_amount() {
	local s
	s="$(format_usd "$1")"
	echo "${s#\$}"
}

widget_error() {
	local target="$1"
	local msg="$2"
	"$TW" --target "$target" \
		--icon exclamationmark.triangle.fill \
		--background "#422006" \
		--foreground "#fde68a" \
		--text "AppFigures: $msg" || true
}

if [[ -z "$TOKEN" ]]; then
	widget_error "$TABLE_TARGET" "APPFIGURES_ACCESS_TOKEN not set"
	exit 1
fi

for cmd in jq curl; do
	if ! command -v "$cmd" >/dev/null 2>&1; then
		widget_error "$TABLE_TARGET" "$cmd required"
		exit 1
	fi
done

if ! command -v "$TW" >/dev/null 2>&1; then
	widget_error "$TABLE_TARGET" "terminal-widget not found"
	exit 1
fi

date_offset_days() {
	local days="$1"
	if date -v-"${days}"d +%Y-%m-%d >/dev/null 2>&1; then
		date -v-"${days}"d +%Y-%m-%d
	elif date -d "${days} days ago" +%Y-%m-%d >/dev/null 2>&1; then
		date -d "${days} days ago" +%Y-%m-%d
	else
		widget_error "$TABLE_TARGET" "date command unsupported"
		exit 1
	fi
}

today="$(date +%Y-%m-%d)"
yesterday="$(date_offset_days 1)"
end_date="$yesterday"

fetch_days=$((DAYS_CHART > DAYS_TABLE ? DAYS_CHART : DAYS_TABLE))
if ((fetch_days > 30)); then
	fetch_days=30
fi
start_date="$(date_offset_days "$fetch_days")"

day_row_is_empty() {
	local row="$1"
	local dl rev rev_int
	[[ -z "$row" ]] && return 0
	IFS=$'\t' read -r _ dl rev <<<"$row"
	rev_int="$(printf '%.0f' "$rev" 2>/dev/null || echo 0)"
	[[ "${dl%.*}" == "0" && "$rev_int" == "0" ]]
}

cached_yesterday_incomplete() {
	local row
	[[ ! -f "$daily_tsv" ]] && return 0
	row="$(grep "^${yesterday}"$'\t' "$daily_tsv" 2>/dev/null | tail -n 1 || true)"
	day_row_is_empty "$row"
}

should_fetch=1
if [[ -f "$CACHE_STAMP" && -f "$CACHE_JSON" && "${APPFIGURES_FORCE_REFRESH:-0}" != "1" ]]; then
	stamp="$(<"$CACHE_STAMP")"
	if [[ "$stamp" == "$today" ]] && ! cached_yesterday_incomplete; then
		should_fetch=0
	fi
fi

if ((should_fetch)); then
	query="start_date=${start_date}&end_date=${end_date}&granularity=daily&group_by=date"
	if [[ -n "${APPFIGURES_PRODUCT_IDS:-}" ]]; then
		query="${query}&products=${APPFIGURES_PRODUCT_IDS}"
	fi
	url="${API_BASE}/reports/sales?${query}"

	if ! json="$(curl -fsS -H "Authorization: Bearer ${TOKEN}" -H "Accept: application/json" "$url")"; then
		widget_error "$TABLE_TARGET" "API request failed"
		exit 1
	fi
	echo "$json" >"$CACHE_JSON"
	echo "$today" >"$CACHE_STAMP"
else
	json="$(<"$CACHE_JSON")"
fi

jq -r '
  def row(d; o):
    [d, (o.downloads // o.net_downloads // o.app_downloads // 0), (o.revenue // 0)];

  def emit(d; o):
    row(d; o) | @tsv;

  if type == "array" then
    .[] | select(.date != null) | emit(.date; .)
  elif type == "object" and ([.[] | type] | all(. == "object")) and ([keys[]][0] | test("^[0-9]{4}-[0-9]{2}-[0-9]{2}")) then
    to_entries[] | emit(.key; .value)
  elif .dates and (.dates | type) == "object" then
    .dates | to_entries[] | emit(.key; .value)
  elif .sales and (.sales | type) == "array" then
    .sales[] | select(.date != null) | emit(.date; .)
  elif type == "object" then
    [to_entries[] | .value | to_entries[] | {date: .key, data: .value}]
    | group_by(.date)
    | .[]
    | {
        date: .[0].date,
        downloads: (map(.data.downloads // .data.net_downloads // .data.app_downloads // 0) | add),
        revenue: (map(.data.revenue // 0) | add)
      }
    | emit(.date; .)
  else
    empty
  end
' <<<"$json" | sort -u >"$daily_tsv"

if [[ ! -s "$daily_tsv" ]]; then
	widget_error "$TABLE_TARGET" "unexpected API response (see cache JSON)"
	exit 1
fi

display_tsv="$daily_tsv"
if [[ "$(tail -n 1 "$daily_tsv" | cut -f1)" == "$today" ]]; then
	display_tsv="$CACHE_DIR/appfigures-daily-display.tsv"
	grep -v "^${today}"$'\t' "$daily_tsv" >"$display_tsv"
fi

table_csv="$CACHE_DIR/appfigures-table.csv"
{
	echo 'Date,Downloads,Revenue'
	tail -n "$DAYS_TABLE" "$display_tsv" | while IFS=$'\t' read -r d dl rev; do
		rev_fmt="$(format_amount "$rev" 2>/dev/null || echo "$rev")"
		printf '%s,%s,%s\n' "$d" "$dl" "$rev_fmt"
	done
} >"$table_csv"

cat "$table_csv" | "$TW" \
	--target "$TABLE_TARGET" \
	--table - \
	--grid zebra-row \
	--table-layout auto \
	--mode dark \
	--text "$TABLE_LABEL" \
	--background "#1e1b4b" \
	--foreground "#e0e7ff"

chart_slice() {
	local field="$1"
	tail -n "$DAYS_CHART" "$display_tsv" | while IFS=$'\t' read -r _ dl rev; do
		if [[ "$field" == "downloads" ]]; then
			echo "$dl"
		else
			printf '%.0f\n' "$rev"
		fi
	done | paste -sd ' ' -
}

dl_values="$(chart_slice downloads)"
rev_values="$(chart_slice revenue)"
start_chart="$(head -n 1 "$display_tsv" | cut -f1)"
end_chart="$(tail -n 1 "$display_tsv" | cut -f1)"

if [[ -n "$dl_values" ]]; then
	"$TW" \
		--target "$DL_CHART_TARGET" \
		--chart "$dl_values" \
		--chart-format sparkline \
		--base-zero \
		--annotate \
		--text "Downloads (${DAYS_CHART}d)" \
		--caption \
		--caption-left "$start_chart" \
		--caption-right "$end_chart" \
		--background "#1e1b4b" \
		--foreground "#a78bfa" \
		--text-color "#e0e7ff" \
		--caption-color "#a5b4fc"
fi

if [[ -n "$rev_values" ]]; then
	"$TW" \
		--target "$REV_CHART_TARGET" \
		--chart "$rev_values" \
		--chart-format sparkline \
		--base-zero \
		--annotate \
		--text "Revenue \$ (${DAYS_CHART}d)" \
		--caption \
		--caption-left "$start_chart" \
		--caption-right "$end_chart" \
		--background "#1e1b4b" \
		--foreground "#34d399" \
		--text-color "#e0e7ff" \
		--caption-color "#a5b4fc"
fi
