#!/usr/bin/sh
set -eu

CONFIG=${YA_CONFIG:-/etc/yabo/config}
# shellcheck source=/dev/null
. "$CONFIG"
LIB=${YA_LIB:-/usr/share/yabo/lib.sh}
# shellcheck source=/dev/null
. "$LIB"

REC="$YA_ROOT/subscriptions.rec"
RSS_PARSE=${YA_RSS_PARSE:-/usr/share/yabo/rss.php}
RUNTIME_DIR=${RUNTIME_DIR:-/run/yabo}
FEEDS="$RUNTIME_DIR/feeds.conf"
MAP="$RUNTIME_DIR/feeds.map"

# Insert-if-absent: an id already present is a no-op. The whole read-decide-
# insert runs under the channel lock so the downloader (which also mutates
# Channel.rec) never interleaves with detection.
upsert_video() {
  ledger=$1; id=$2; published=$3; title=$4
  ensure_channel_rec "$ledger"
  ( flock 9
    if [ -z "$(recsel -t Video -e "Id = '$id'" "$ledger")" ]; then
      recins -t Video -f Id -v "$id" \
        -f Published -v "$published" -f Title -v "$title" "$ledger"
    fi
  ) 9>"$(dirname "$ledger")/.channel.lock"
}

mkdir -p "$RUNTIME_DIR"
: > "$FEEDS"
: > "$MAP"

# curl --etag-compare treats a missing etag file as an empty etag, so every
# block is uniform — no per-channel conditional logic needed.
{
  echo 'parallel'
  echo 'http2'
} >> "$FEEDS"

# -C prints values with no separator, so a record missing ChannelId would
# desync the url/cid pairing below; require #ChannelId to keep them aligned
# (a legacy sub without an id can't be fetched by channel_id anyway).
recsel -t Subscription -C -e "(#Enabled = 0 || Enabled = 'yes') && #ChannelId = 1" \
  -P Url,ChannelId "$REC" \
| while IFS= read -r url && IFS= read -r cid; do
    dir="$YA_ROOT/$(sanitize "$url")"
    mkdir -p "$dir"   # detection may run before the first download creates it
    printf '%s\t%s\n' "$cid" "$dir" >> "$MAP"
    # --next opens each request; leading (not trailing) so no empty final
    # transfer (a trailing --next makes curl exit 2 "no URL specified").
    {
      echo '--next'
      echo 'url = "https://www.youtube.com/feeds/videos.xml?channel_id='"$cid"'"'
      # write-out must live in each --next block: curl applies it per operation,
      # so a single global one reports only the first transfer and silently
      # drops the rest. printf (not echo) keeps the literal \n curl needs.
      printf 'write-out = "%%{http_code} %%{url}\\n"\n'
      echo 'etag-compare = "'"$dir"'/.rss-etag"'
      echo 'etag-save = "'"$dir"'/.rss-etag"'
      echo 'output = "'"$dir"'/.rss-feed.new"'
    } >> "$FEEDS"
  done

# Nothing enabled -> only the global block, no --next: skip the fetch.
grep -q '^url = ' "$FEEDS" || exit 0

# One multiplexed conditional GET over a single h2 connection.
SUMMARY=$(curl -K "$FEEDS")

printf '%s\n' "$SUMMARY" | while IFS=' ' read -r code url; do
  [ "$code" = "200" ] || continue   # 304 (or anything else) -> ledger untouched
  cid=$(printf '%s' "$url" | sed -n 's/.*channel_id=\([^&]*\).*/\1/p')
  [ -n "$cid" ] || continue
  dir=$(awk -F '\t' -v c="$cid" '$1 == c {print $2; exit}' "$MAP")
  [ -n "$dir" ] || continue
  feed="$dir/.rss-feed.new"
  [ -f "$feed" ] || continue
  ledger="$dir/Channel.rec"
  ensure_channel_rec "$ledger"
  php "$RSS_PARSE" "$feed" \
  | while IFS= read -r line; do
      case $line in
        'Id: '*) vid=${line#Id: } ;;
        'Published: '*) vpub=${line#Published: } ;;
        'Title: '*) vtitle=${line#Title: } ;;
        '') [ -n "${vid:-}" ] && upsert_video "$ledger" "$vid" "${vpub:-}" "${vtitle:-}"
            vid=; vpub=; vtitle= ;;
      esac
    done
done
