#!/usr/bin/env bash
# Re-select a poster for items whose poster is missing or does not resolve.
set -euo pipefail

readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly COLLECTION_DIR="$(dirname "$SCRIPT_DIR")"

# shellcheck source=../lib/plex-api.sh
. "$COLLECTION_DIR/lib/plex-api.sh"
# shellcheck source=../lib/posters.sh
. "$COLLECTION_DIR/lib/posters.sh"

SECTION="TV Shows"
TYPE=2
DRY_RUN=0
LIMIT=0
export POSTER_ALLOW_REMOTE=0

# Global, not local to main(): an EXIT trap fires after main() returns, by which
# point a local would be out of scope and `set -u` would abort the cleanup.
WORKDIR=""
cleanup() { [[ -n "$WORKDIR" ]] && rm -rf "$WORKDIR"; return 0; }
trap cleanup EXIT

usage() {
  cat <<'EOF'
Usage: poster-repair [--dry-run] [--section <id|title>] [--type <n>]
                     [--limit N] [--allow-remote]

  --dry-run       Show what would be selected; change nothing.
  --section       Library section, by id or exact title. Default: "TV Shows".
  --type          Plex type code: 1=movie 2=show 3=season 4=episode. Default: 2.
  --limit N       Repair at most N items (0 = no limit).
  --allow-remote  Also repair items with no locally-cached poster by pulling
                  one from the metadata agent. Off by default: it re-downloads
                  from the internet and may pick a different image than the one
                  that was originally chosen.
  --jobs N        Parallel HTTP checks during the scan (default 8).
  --help

What it does: for each broken item it selects the poster already sitting in
that item's metadata bundle. The image is not re-downloaded and no other
metadata is touched, so this does not overwrite manually-chosen artwork —
items that still have a working poster are skipped entirely.

Idempotent: re-running repairs nothing once every poster resolves.
EOF
}

main() {
  while (( $# )); do
    case "$1" in
      --dry-run)      DRY_RUN=1 ;;
      --section)      SECTION="${2:?--section needs a value}"; shift ;;
      --type)         TYPE="${2:?--type needs a value}"; shift ;;
      --limit)        LIMIT="${2:?--limit needs a value}"; shift ;;
      --allow-remote) POSTER_ALLOW_REMOTE=1 ;;
      --jobs)         POSTER_JOBS="${2:?--jobs needs a value}"; export POSTER_JOBS; shift ;;
      --help|-h)      usage; exit 0 ;;
      *) plex_die "unknown argument: $1 (try --help)" ;;
    esac
    shift
  done

  plex_require_deps
  plex_load_env "$COLLECTION_DIR/.env"
  plex_check_auth

  local section_id
  section_id="$(posters_resolve_section "$SECTION")"

  WORKDIR="$(mktemp -d)"

  plex_log "Scanning section '${SECTION}' (id ${section_id}, type ${TYPE})..."
  posters_fetch_items "$section_id" "$TYPE" "$WORKDIR/items.json"
  posters_scan "$WORKDIR/items.json" | awk -F'\t' '$2!="OK"' | sort -t$'\t' -k3 > "$WORKDIR/broken.tsv"

  local count
  count="$(wc -l < "$WORKDIR/broken.tsv" | tr -d ' ')"
  if (( count == 0 )); then
    plex_log "Nothing to repair — every poster resolves."
    return 0
  fi
  plex_log "Found ${count} item(s) needing repair."
  (( DRY_RUN )) && plex_log "[dry-run] no changes will be made."
  plex_log ""

  local repaired=0 skipped=0 failed=0 processed=0
  local rk status title candidate
  while IFS=$'\t' read -r rk status title; do
    if (( LIMIT > 0 && processed >= LIMIT )); then
      plex_log "Reached --limit ${LIMIT}; stopping."
      break
    fi
    processed=$((processed + 1))

    candidate="$(posters_candidate "$rk")" || candidate=""
    if [[ -z "$candidate" ]]; then
      plex_warn "SKIP   ${title} (${rk}, ${status}) — no locally-cached poster; retry with --allow-remote"
      skipped=$((skipped + 1))
      continue
    fi

    if (( DRY_RUN )); then
      plex_log "[dry-run] would select for ${title} (${rk}): ${candidate:0:72}"
      repaired=$((repaired + 1))
      continue
    fi

    if ! posters_select "$rk" "$candidate"; then
      plex_warn "FAIL   ${title} (${rk}) — poster selection rejected"
      failed=$((failed + 1))
      continue
    fi

    if posters_verify "$rk"; then
      plex_log "OK     ${title} (${rk})"
      repaired=$((repaired + 1))
    else
      plex_warn "FAIL   ${title} (${rk}) — selected, but thumb still does not resolve"
      failed=$((failed + 1))
    fi
  done < "$WORKDIR/broken.tsv"

  plex_log ""
  if (( DRY_RUN )); then
    plex_log "Summary (dry-run): ${repaired} would be repaired, ${skipped} skipped."
  else
    plex_log "Summary: ${repaired} repaired, ${skipped} skipped, ${failed} failed."
  fi
  (( failed == 0 ))
}

main "$@"
