#!/bin/bash
# ==============================================================================================
# =========================== Playback-Aware Radarr Discovery ==================================
# ==============================================================================================
#
# PURPOSE
# ─────────────────────────────────────────────────────────────────────────────
# Two-stage behavior-driven movie discovery.
#
# Stage 1 — Score recently watched movies in Emby. The top movies become
#            high-quality seeds, weighted by recency and TMDB rating.
#
# Stage 2 — Run TMDB recommendations on those seeds. Score the candidates
#            and add the top movies to Radarr.
#
# Goal: 0–5 meaningful Radarr adds per run, not bulk imports.
#
# ==============================================================================================
# OPERATIONAL MODEL
# ==============================================================================================
#
#   1. Fetch recently watched movies from Emby (SEED_LIBRARIES, last LOOKBACK_DAYS days)
#      — only movies with a TMDB ID are eligible as seeds
#
#   ── Stage 1 ─────────────────────────────────────────────────────────────────
#   2. Score each watched movie: recency + TMDB rating + vote count
#   3. Take top MAX_SEEDS by score → discovery seeds
#
#   ── Stage 2 ─────────────────────────────────────────────────────────────────
#   4. For each seed, call TMDB movie recommendations → collect candidates
#   5. Aggregate: breadth (distinct seeds recommending this movie)
#   6. Filter: already in Radarr, already in Emby, below min votes/rating, cooldown
#   7. Score candidates: breadth + TMDB rating + vote count
#   8. Take top MAX_ADDS above threshold → add to Radarr
#
# Step 6's "already in Radarr" check reads the shared tracked-data cache via
# arr_get_tracked_data() (cache-first, live fallback, 2026-07-17) instead of a live fetch —
# this runs weekly right after arr_full_rescan.sh, so it's reading the genuine post-rescan
# snapshot arr_full_rescan.sh just wrote.
#
# ==============================================================================================
# SCORING MODEL
# ==============================================================================================
#
#   Stage 1 — seed selection (max 100)
#     recency_score    (0-50) — days since last watch; 0-3d→50, 4-7d→40, 8-14d→30, 15-21d→20, 22-30d→10
#     rating_score     (0-30) — TMDB vote_average: 8.0+→30, 7.5+→25, 7.0+→18, 6.5+→12, 6.0+→8, else→3
#     votes_score      (0-20) — TMDB vote_count: 10k+→20, 5k+→15, 1k+→10, 200+→5, else→2
#
#   Stage 2 — candidate scoring (max 100)
#     breadth_score    (0-40) — 3+ seeds→40, 2 seeds→25, 1 seed→10
#     rating_score     (0-40) — TMDB vote_average: 8.0+→40, 7.5+→32, 7.0+→25, 6.5+→18, 6.0+→12, else→5
#     votes_score      (0-20) — TMDB vote_count (same thresholds)
#
#   Threshold: RADARR_DISCOVERY_THRESHOLD (default 60) — lower than Lidarr since tastes are broader
#   Max adds:  RADARR_DISCOVERY_MAX_ADDS (default 5)
#
# ==============================================================================================
# CONFIGURATION
# ==============================================================================================
#
# host*.conf (aliased by detect_hosts())
#
#   HOST*_TMDB_API_KEY   Required for Stage 2 recommendations. Free key at
#                        https://www.themoviedb.org/settings/api — without it the run
#                        exits cleanly rather than adding anything unscored.
#   RADARR_URL / RADARR_API_KEY   Target arr
#   EMBY_URL / EMBY_API_KEY       Play history source for seed selection
#
# master.conf
#
#   RADARR_DISCOVERY_THRESHOLD          Score required to accept a candidate (0-100)
#   RADARR_DISCOVERY_LOOKBACK_DAYS      Emby watch history window
#   RADARR_DISCOVERY_MAX_SEEDS          Max seed movies taken from Stage 1
#   RADARR_DISCOVERY_MAX_ADDS           Hard cap on movies added per run
#   RADARR_DISCOVERY_MIN_VOTE_COUNT     Min TMDB votes for a candidate to be considered
#   RADARR_DISCOVERY_MIN_RATING         Min TMDB vote_average × 10
#   RADARR_DISCOVERY_REJECT_COOLDOWN    Days before a rejected movie is re-evaluated
#   RADARR_DISCOVERY_SEED_LIBRARIES     Emby libraries to draw seed movies from
#   RADARR_DISCOVERY_HISTORY            Decision history DB — accepted and rejected
#
# ==============================================================================================
# DESIGN PRINCIPLES
# ==============================================================================================
#
# Playback as Intent Signal
#   Recently watched movies are a stronger signal than what is in the library or
#   on watchlists. The scoring model weights demonstrated viewing behaviour —
#   recency, rating, vote confidence — over passive ownership.
#
# Selective by Design
#   0–5 adds per run is the target, not bulk imports. A score threshold combined
#   with MAX_ADDS ensures only high-confidence recommendations are acted on.
#   Volume is not the goal — meaningful discovery is.
#
# Two-Stage Filtering
#   Stage 1 rejects weak seeds before they drive Stage 2. Low-quality or
#   low-confidence watched movies produce poor recommendations. Filtering at
#   the seed stage improves the entire output.
#
# ==============================================================================================
# OPERATIONAL SAFEGUARDS
# ==============================================================================================
#
# Root Required
#   acquire_lock and Radarr API writes require root. Script exits cleanly if not root.
#
# Dry-Run Mode
#   --dry-run scores and ranks all candidates but makes no Radarr API calls and does not
#   write to the history file. Safe to run at any time to preview what would be added.
#
# Add-Only
#   Only adds movies to Radarr. Never deletes or modifies existing entries.
#
# Cooldown Guard
#   Candidates rejected this run are recorded in the history file and not re-evaluated
#   until RADARR_DISCOVERY_REJECT_COOLDOWN days have elapsed.
#
# ==============================================================================================
# STATE FILES
# ==============================================================================================
#
#   RADARR_DISCOVERY_HISTORY (default: $DATA_DIR/radarr_discovery_history.db)
#     Tracks added movies and rejected candidates with timestamps. Written after every
#     non-dry-run. Enforces reject cooldown and prevents re-adding items added by previous
#     runs. Safe to delete — next run starts fresh with no memory.
#
# ==============================================================================================
# CONFIGURATION (master.conf)
# ==============================================================================================
#
#   RADARR_DISCOVERY_THRESHOLD        — minimum score to add a candidate (default: 52)
#   RADARR_DISCOVERY_LOOKBACK_DAYS    — Emby watch history window in days (default: 30)
#   RADARR_DISCOVERY_MAX_SEEDS        — max seed movies from Stage 1 (default: 5)
#   RADARR_DISCOVERY_MAX_ADDS         — max movies to add per run (default: 5)
#   RADARR_DISCOVERY_MIN_VOTE_COUNT   — min TMDB votes for a candidate (default: 100)
#   RADARR_DISCOVERY_MIN_RATING       — min TMDB vote_average × 10 (default: 60 = 6.0/10)
#   RADARR_DISCOVERY_REJECT_COOLDOWN  — days before re-evaluating a rejected movie (default: 60)
#   RADARR_DISCOVERY_SEED_LIBRARIES   — Emby library names to draw seeds from (default: ("Movies"))
#   RADARR_DISCOVERY_HISTORY          — history/state file path
#
# ==============================================================================================
# RUNTIME MODES
# ==============================================================================================
#
#   playback_aware_radarr_discovery.sh            — normal run
#   playback_aware_radarr_discovery.sh --dry-run  — score and rank, no Radarr changes
#   playback_aware_radarr_discovery.sh --log      — verbose output
#   playback_aware_radarr_discovery.sh --status   — show config and exit
#
# Recommended schedule: weekly (WEEKLY_MAINTENANCE_SCRIPTS in master.conf)
#
# ==============================================================================================

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

source "$SCRIPT_DIR/../load_config.sh"

parse_args "$@"

# ==============================================================================================
# ━━━ Setup ━━━
# ==============================================================================================
if [[ "$EUID" -ne 0 ]]; then
    error "Must be run as root"
    exit 1
fi

acquire_lock
detect_hosts

if ! command -v jq >/dev/null 2>&1; then
    error "jq not installed — required for API JSON parsing"
    exit 1
fi

if [[ -z "${EMBY_URL:-}" || -z "${EMBY_API_KEY:-}" ]]; then
    error "EMBY_URL / EMBY_API_KEY not configured — check host*.conf"
    exit 1
fi

if [[ -z "${RADARR_URL:-}" || -z "${RADARR_API_KEY:-}" ]]; then
    error "RADARR_URL / RADARR_API_KEY not configured — check host*.conf"
    exit 1
fi

if [[ -z "${TMDB_API_KEY:-}" ]]; then
    error "TMDB_API_KEY not configured — required for discovery"
    error "Get a free key at https://www.themoviedb.org/settings/api"
    error "Configure HOST*_TMDB_API_KEY in host*.conf"
    exit 1
fi

THRESHOLD="${RADARR_DISCOVERY_THRESHOLD:-60}"
LOOKBACK_DAYS="${RADARR_DISCOVERY_LOOKBACK_DAYS:-30}"
MAX_SEEDS="${RADARR_DISCOVERY_MAX_SEEDS:-5}"
MAX_ADDS="${RADARR_DISCOVERY_MAX_ADDS:-5}"
MIN_VOTE_COUNT="${RADARR_DISCOVERY_MIN_VOTE_COUNT:-100}"
MIN_RATING="${RADARR_DISCOVERY_MIN_RATING:-60}"
REJECT_COOLDOWN="${RADARR_DISCOVERY_REJECT_COOLDOWN:-60}"
HISTORY_FILE="${RADARR_DISCOVERY_HISTORY:-${DATA_DIR}/radarr_discovery_history.db}"
SEED_LIBRARIES=("${RADARR_DISCOVERY_SEED_LIBRARIES[@]:-Movies}")

log "$ICON_GEAR Config: threshold=${THRESHOLD} lookback=${LOOKBACK_DAYS}d max-seeds=${MAX_SEEDS} max-adds=${MAX_ADDS} min-votes=${MIN_VOTE_COUNT} min-rating=${MIN_RATING} reject-cooldown=${REJECT_COOLDOWN}d"

[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no movies will be added to Radarr"

# _fmt_rating() — provided by common.sh

# ==============================================================================================
# ━━━ Status ━━━
# ==============================================================================================
if [[ "$SHOW_STATUS" == true ]]; then
    echo ""
    echo "━━━━━ $ICON_SUMMARY RADARR DISCOVERY STATUS ━━━━━"
    echo "$ICON_HOST    Identity:      $MY_ID ($LOCAL_SERVER_NAME)"
    echo "$ICON_SYNC    Emby:          ${EMBY_URL}"
    echo "$ICON_SYNC    Radarr:        ${RADARR_URL}"
    echo "$ICON_GEAR    Threshold:     ${THRESHOLD} / 100"
    echo "$ICON_TIME    Lookback:      ${LOOKBACK_DAYS} days"
    echo "$ICON_GEAR    Max seeds:     ${MAX_SEEDS}"
    echo "$ICON_GEAR    Max adds:      ${MAX_ADDS}"
    echo "$ICON_GEAR    Min rating:    ${MIN_RATING} ($(_fmt_rating "$MIN_RATING")/10 TMDB)"
    echo "$ICON_GEAR    Min votes:     ${MIN_VOTE_COUNT}"
    echo "$ICON_GEAR    Reject TTL:    ${REJECT_COOLDOWN} days"
    echo "$ICON_GEAR    Seed libs:     ${SEED_LIBRARIES[*]}"
    echo "$ICON_GEAR    History file:  ${HISTORY_FILE}"
    echo "$ICON_GEAR    TMDB:          configured"
    echo "$ICON_GEAR    Dry Run:       $DRY_RUN"
    echo "━━━━━━━━━━━━━━━━━━━━━━━"
    exit 0
fi

# ==============================================================================================
# ── API HELPERS ───────────────────────────────────────────────────────────────────────────────
# ==============================================================================================


_radarr_get() {
    curl -sf --max-time 20 \
        -H "X-Api-Key: $RADARR_API_KEY" \
        "${RADARR_URL}/api/v3/${1}" 2>/dev/null
}

_radarr_lookup() {
    curl -sf --max-time 20 --get \
        --data-urlencode "term=tmdb:${1}" \
        -H "X-Api-Key: $RADARR_API_KEY" \
        "${RADARR_URL}/api/v3/movie/lookup" 2>/dev/null
}

_radarr_post() {
    curl -sf --max-time 20 -X POST \
        -H "X-Api-Key: $RADARR_API_KEY" \
        -H "Content-Type: application/json" \
        -d "$1" \
        "${RADARR_URL}/api/v3/movie" 2>/dev/null
}

_radarr_command() {
    curl -sf --max-time 20 -X POST \
        -H "X-Api-Key: $RADARR_API_KEY" \
        -H "Content-Type: application/json" \
        -d "$1" \
        "${RADARR_URL}/api/v3/command" 2>/dev/null
}

_tmdb_recommendations() {
    curl -sf --max-time 15 \
        "https://api.themoviedb.org/3/movie/${1}/recommendations?api_key=${TMDB_API_KEY}&language=en-US&page=1" \
        2>/dev/null
}

# ==============================================================================================
# ── SCORING HELPERS ───────────────────────────────────────────────────────────────────────────
# ==============================================================================================

_recency_score() {
    local days="$1"
    if   (( days <= 3  )); then echo 50
    elif (( days <= 7  )); then echo 40
    elif (( days <= 14 )); then echo 30
    elif (( days <= 21 )); then echo 20
    elif (( days <= 30 )); then echo 10
    else                        echo 0
    fi
}

# Stage 1: play frequency score (max 50) — complements recency (max 50) for 100 total
_freq_score() {
    local c="$1"
    if   (( c >= 4 )); then echo 50
    elif (( c >= 2 )); then echo 35
    else                    echo 20
    fi
}

# _rating_score_s2(), _votes_score(), _breadth_score() — provided by common.sh

# ==============================================================================================
# ━━━ Fetch Emby Libraries + Recently Watched Movies ━━━
# ==============================================================================================
echo ""
echo "━━━━━ $ICON_SUMMARY Radarr Discovery — $(date '+%Y-%m-%d %H:%M:%S') ━━━━━"
echo "$ICON_HOST $MY_ID ($LOCAL_SERVER_NAME) | lookback: ${LOOKBACK_DAYS}d | threshold: ${THRESHOLD}/100 | max: ${MAX_ADDS}"
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no movies will be added"

echo ""
echo "━━━ $ICON_SYNC Emby Watch History ━━━"

LIBRARIES_JSON=$(emby_api "Library/VirtualFolders") || { error "Could not fetch Emby libraries"; exit 1; }
CUTOFF_ISO=$(date -d "${LOOKBACK_DAYS} days ago" '+%Y-%m-%dT%H:%M:%SZ')
TODAY_EPOCH=$(date +%s)
TODAY=$(date +%Y-%m-%d)

# Build TMDB index of all movies in Emby — used in Stage 2 to filter already-owned movies
declare -A EMBY_TMDB_IDS   # tmdb_id → 1

for lib_name in "${SEED_LIBRARIES[@]}"; do
    lib_id=$(echo "$LIBRARIES_JSON" | jq -r --arg n "$lib_name" '.[] | select(.Name == $n) | .ItemId' 2>/dev/null)
    if [[ -z "$lib_id" ]]; then
        warn "Emby library not found: $lib_name"
        continue
    fi
    log "Indexing library: $lib_name (ItemId: $lib_id)"
    LIB_JSON=$(emby_api "Items?ParentId=${lib_id}&IncludeItemTypes=Movie&Recursive=true&Fields=ProviderIds&Limit=10000") || {
        warn "Could not index library: $lib_name"
        continue
    }
    while IFS= read -r tmdb_id; do
        [[ -n "$tmdb_id" && "$tmdb_id" != "null" ]] && EMBY_TMDB_IDS["$tmdb_id"]=1
    done < <(echo "$LIB_JSON" | jq -r '.Items[].ProviderIds.Tmdb // empty' 2>/dev/null)
done
log "${#EMBY_TMDB_IDS[@]} movies in Emby TMDB index"

# Fetch recent play completions from the server-level activity log.
# Each entry includes an ItemId — batch-fetch those items to determine type (Movie vs. Music/TV).
# SortBy=DatePlayed on Items requires UserId context and errors without one; the activity log
# is server-scoped and doesn't have that limitation.
ACTIVITY_JSON=$(emby_api "System/ActivityLog/Entries?MinDate=${CUTOFF_ISO}&Limit=5000") || {
    error "Could not fetch Emby activity log"
    exit 1
}

declare -A ITEM_PLAYS      # emby_item_id → play count
declare -A ITEM_LAST_PLAY  # emby_item_id → ISO date of most recent play

while IFS='|' read -r item_id play_date; do
    [[ -z "$item_id" || "$item_id" == "null" ]] && continue
    ITEM_PLAYS["$item_id"]=$(( ${ITEM_PLAYS["$item_id"]:-0} + 1 ))
    current="${ITEM_LAST_PLAY["$item_id"]:-}"
    if [[ -z "$current" || "$play_date" > "$current" ]]; then
        ITEM_LAST_PLAY["$item_id"]="$play_date"
    fi
done < <(echo "$ACTIVITY_JSON" | jq -r '
    .Items[] | select(.Type == "playback.stop") | select(.ItemId != null and .ItemId != "") |
    [.ItemId, .Date] | join("|")
' 2>/dev/null)

log "${#ITEM_PLAYS[@]} unique items in activity log"

declare -A WATCHED_MOVIES   # tmdb_id → "title|play_count|last_play_date"

if [[ "${#ITEM_PLAYS[@]}" -gt 0 ]]; then
    # Fetch in batches of 100 — large ID lists exceed GET URL limits
    ALL_ITEM_IDS=("${!ITEM_PLAYS[@]}")
    BATCH_SIZE=100
    for (( _b=0; _b<${#ALL_ITEM_IDS[@]}; _b+=BATCH_SIZE )); do
        BATCH=("${ALL_ITEM_IDS[@]:_b:BATCH_SIZE}")
        IDS_CSV=$(printf '%s,' "${BATCH[@]}"); IDS_CSV="${IDS_CSV%,}"
        ITEMS_DETAIL=$(emby_api "Items?Ids=${IDS_CSV}&Fields=ProviderIds,Type&Limit=200") || {
            warn "Could not fetch item batch starting at $_b"
            continue
        }
        while IFS='|' read -r item_id item_type tmdb_id title; do
            [[ "$item_type" != "Movie" ]] && continue
            [[ -z "$tmdb_id" || "$tmdb_id" == "null" ]] && continue
            play_count="${ITEM_PLAYS["$item_id"]:-1}"
            last_play="${ITEM_LAST_PLAY["$item_id"]:-}"
            if [[ -n "${WATCHED_MOVIES["$tmdb_id"]:-}" ]]; then
                IFS='|' read -r ex_title ex_plays ex_date <<< "${WATCHED_MOVIES["$tmdb_id"]}"
                play_count=$(( ex_plays + play_count ))
                [[ "$last_play" > "$ex_date" ]] || last_play="$ex_date"
                title="$ex_title"
            fi
            WATCHED_MOVIES["$tmdb_id"]="${title}|${play_count}|${last_play}"
        done < <(echo "$ITEMS_DETAIL" | jq -r '.Items[] |
            [(.Id | tostring), .Type, (.ProviderIds.Tmdb // ""), .Name] | join("|")
        ' 2>/dev/null)
    done
fi

WATCHED_COUNT=${#WATCHED_MOVIES[@]}
log "$WATCHED_COUNT movies watched in the last ${LOOKBACK_DAYS} days with TMDB IDs"

if [[ "$WATCHED_COUNT" -eq 0 ]]; then
    warn "No recently watched movies found — nothing to seed from"
    exit 0
fi

# ==============================================================================================
# ━━━ Stage 1: Score Watched Movies → Select Seeds ━━━
# ==============================================================================================
# Scoring: recency (0-50) + play frequency across all users (0-50) = max 100
# No TMDB rating at Stage 1 — CommunityRating is not exposed by Emby's Items API
echo ""
echo "━━━ $ICON_GEAR Stage 1: Scoring Watched Movies ━━━"

S1_SCORED=()  # "score|tmdb_id|title"

for tmdb_id in "${!WATCHED_MOVIES[@]}"; do
    IFS='|' read -r title play_count last_play <<< "${WATCHED_MOVIES["$tmdb_id"]}"

    last_epoch=$(date -d "$last_play" +%s 2>/dev/null || echo "$TODAY_EPOCH")
    days_ago=$(( (TODAY_EPOCH - last_epoch) / 86400 ))

    recency_s=$(_recency_score "$days_ago")
    freq_s=$(_freq_score "$play_count")
    total=$(( recency_s + freq_s ))

    log "  [${total}] $title (TMDB: $tmdb_id | ${days_ago}d ago | plays: $play_count)"
    S1_SCORED+=("${total}|${tmdb_id}|${title}")
done

IFS=$'\n' S1_SORTED=($(printf '%s\n' "${S1_SCORED[@]}" | sort -t'|' -k1 -rn 2>/dev/null))

echo ""
echo "━━━ $ICON_SUMMARY Stage 1 Results (top ${MAX_SEEDS} seeds) ━━━"

SEEDS_TMDB=()
SEEDS_TITLES=()

for _entry in "${S1_SORTED[@]}"; do
    (( ${#SEEDS_TMDB[@]} >= MAX_SEEDS )) && break
    _score="${_entry%%|*}"
    _rest="${_entry#*|}"
    _tmdb="${_rest%%|*}"
    _title="${_rest#*|}"
    SEEDS_TMDB+=("$_tmdb")
    SEEDS_TITLES+=("$_title")
    printf "  Seed [%3s] %s (TMDB: %s)\n" "$_score" "$_title" "$_tmdb"
done

if [[ "${#SEEDS_TMDB[@]}" -eq 0 ]]; then
    warn "No recently watched movies qualify — no seeds for discovery"
    exit 0
fi

log "${#SEEDS_TMDB[@]} seed(s) selected"

# ==============================================================================================
# ━━━ Stage 2: TMDB Recommendations ━━━
# ==============================================================================================
echo ""
echo "━━━ $ICON_SYNC Stage 2: TMDB Recommendations ━━━"

declare -A CANDIDATE_SEEDS      # tmdb_id → seed count
declare -A CANDIDATE_TITLE      # tmdb_id → title
declare -A CANDIDATE_RATING     # tmdb_id → vote_avg_int
declare -A CANDIDATE_VOTES      # tmdb_id → vote_count

for (( _i=0; _i<${#SEEDS_TMDB[@]}; _i++ )); do
    seed_tmdb="${SEEDS_TMDB[$_i]}"
    seed_title="${SEEDS_TITLES[$_i]}"

    log "  Seed: $seed_title (TMDB: $seed_tmdb)"

    RECS_JSON=$(_tmdb_recommendations "$seed_tmdb")
    if [[ -z "$RECS_JSON" ]] || echo "$RECS_JSON" | jq -e '.results == [] or .results == null' >/dev/null 2>&1; then
        warn "  No TMDB recommendations for: $seed_title"
        continue
    fi

    while IFS='|' read -r rec_id rec_title rec_avg rec_votes; do
        [[ -z "$rec_id" || "$rec_id" == "null" ]] && continue
        [[ "$rec_id" == "$seed_tmdb" ]] && continue

        vote_avg_int=$(echo "$rec_avg" | awk '{printf "%d", $1 * 10 + 0.5}' 2>/dev/null)
        vote_avg_int=${vote_avg_int:-0}
        rec_votes=${rec_votes:-0}

        CANDIDATE_SEEDS["$rec_id"]=$(( ${CANDIDATE_SEEDS["$rec_id"]:-0} + 1 ))
        CANDIDATE_TITLE["$rec_id"]="$rec_title"
        CANDIDATE_RATING["$rec_id"]="$vote_avg_int"
        CANDIDATE_VOTES["$rec_id"]="$rec_votes"
    done < <(echo "$RECS_JSON" | jq -r '.results[] |
        [
            (.id | tostring),
            .title,
            (.vote_average | tostring),
            (.vote_count | tostring)
        ] | join("|")' 2>/dev/null)
done

CANDIDATE_COUNT=${#CANDIDATE_SEEDS[@]}
log "$CANDIDATE_COUNT discovery candidates from TMDB"

if [[ "$CANDIDATE_COUNT" -eq 0 ]]; then
    warn "No candidates returned from TMDB — check API key"
    exit 0
fi

# ==============================================================================================
# ━━━ Fetch Existing Radarr Library ━━━
# ==============================================================================================
echo ""
echo "━━━ $ICON_SYNC Existing Libraries ━━━"

# Cache-first — arr_get_tracked_data() serves the shared cache when it's fresh (kept current
# every 30min by arr_cache_prefill.sh in CRITICAL_MAINTENANCE_SCRIPTS), falls back to a live
# fetch when it's stale, and waits out an active rescan before either.
RADARR_MOVIES_JSON=$(arr_get_tracked_data "radarr" "$RADARR_URL" "$RADARR_API_KEY" "v3") || { error "Could not fetch Radarr library"; exit 1; }

declare -A RADARR_TMDB   # tmdb_id → 1
while read -r tmdb_id; do
    [[ -n "$tmdb_id" && "$tmdb_id" != "0" ]] && RADARR_TMDB["$tmdb_id"]=1
done < <(echo "$RADARR_MOVIES_JSON" | jq -r '.[].tmdbId // 0 | tostring' 2>/dev/null)

RADARR_COUNT=${#RADARR_TMDB[@]}
EMBY_COUNT=${#EMBY_TMDB_IDS[@]}
log "$RADARR_COUNT movies in Radarr | $EMBY_COUNT movies in Emby"

_in_radarr() { [[ "${RADARR_TMDB["$1"]+x}" ]]; }
_in_emby()   { [[ "${EMBY_TMDB_IDS["$1"]+x}" ]]; }

# ==============================================================================================
# ━━━ Score Stage 2 Candidates ━━━
# ==============================================================================================
echo ""
echo "━━━ $ICON_GEAR Stage 2: Scoring Candidates ━━━"

ACCEPT_LIST=()
REJECT_LIST=()
ALREADY_KNOWN=0
SKIP_COOLDOWN=0
SKIP_QUALITY=0

for rec_id in "${!CANDIDATE_SEEDS[@]}"; do
    seed_count="${CANDIDATE_SEEDS["$rec_id"]}"
    title="${CANDIDATE_TITLE["$rec_id"]}"
    vote_avg_int="${CANDIDATE_RATING["$rec_id"]}"
    vote_count="${CANDIDATE_VOTES["$rec_id"]}"

    if _in_radarr "$rec_id"; then
        (( ALREADY_KNOWN++ ))
        log "  $ICON_SKIP In Radarr: $title"
        continue
    fi

    if _in_emby "$rec_id"; then
        (( ALREADY_KNOWN++ ))
        log "  $ICON_SKIP In Emby: $title"
        continue
    fi

    # Hard quality floor — skip before cooldown check to avoid polluting history
    if (( vote_count < MIN_VOTE_COUNT || vote_avg_int < MIN_RATING )); then
        (( SKIP_QUALITY++ ))
        log "  $ICON_SKIP Below quality floor (rating: $(_fmt_rating "$vote_avg_int") | votes: $vote_count): $title"
        continue
    fi

    if [[ -f "$HISTORY_FILE" ]]; then
        last_rejection=$(grep -i "^REJECT|${rec_id}|" "$HISTORY_FILE" 2>/dev/null | tail -1 | cut -d'|' -f3)
        if [[ -n "$last_rejection" ]]; then
            last_epoch=$(date -d "$last_rejection" +%s 2>/dev/null || echo 0)
            days_since=$(( (TODAY_EPOCH - last_epoch) / 86400 ))
            if (( days_since < REJECT_COOLDOWN )); then
                (( SKIP_COOLDOWN++ ))
                log "  $ICON_SKIP Cooldown (rejected ${days_since}d ago): $title"
                continue
            fi
        fi
    fi

    breadth_s=$(_breadth_score "$seed_count")
    rating_s=$(_rating_score_s2 "$vote_avg_int")
    votes_s=$(_votes_score "$vote_count")
    total=$(( breadth_s + rating_s + votes_s ))

    entry="${total}|${rec_id}|${title}|${seed_count}|${vote_avg_int}|${vote_count}"
    if (( total >= THRESHOLD )); then
        ACCEPT_LIST+=("$entry")
    else
        REJECT_LIST+=("$entry")
    fi

    log "  [${total}] $title (seeds: $seed_count | rating: $(_fmt_rating "$vote_avg_int") | votes: $vote_count)"
done

# ==============================================================================================
# ━━━ Results ━━━
# ==============================================================================================
echo ""
echo "━━━ $ICON_SUMMARY Stage 2 Results (threshold: ${THRESHOLD}, max: ${MAX_ADDS}) ━━━"

IFS=$'\n' _ALL_ACCEPTS=($(printf '%s\n' "${ACCEPT_LIST[@]}" | sort -t'|' -k1 -rn 2>/dev/null))
IFS=$'\n' SORTED_REJECTS=($(printf '%s\n' "${REJECT_LIST[@]}" | sort -t'|' -k1 -rn 2>/dev/null))

SORTED_ACCEPTS=("${_ALL_ACCEPTS[@]:0:$MAX_ADDS}")
for (( _i=MAX_ADDS; _i<${#_ALL_ACCEPTS[@]}; _i++ )); do
    SORTED_REJECTS+=("${_ALL_ACCEPTS[$_i]}")
done

_print_row() {
    local label="$1" entry="$2"
    IFS='|' read -r score rec_id title seeds avg_int votes <<< "$entry"
    local rating_fmt
    rating_fmt=$(_fmt_rating "$avg_int")
    printf "  %-8s [%3s] %-45s seeds: %s | rating: %s | votes: %s\n" \
        "$label" "$score" "$title" "$seeds" "$rating_fmt" "$votes"
}

for entry in "${SORTED_ACCEPTS[@]}"; do [[ -n "$entry" ]] && _print_row "ACCEPT" "$entry"; done
for entry in "${SORTED_REJECTS[@]}"; do [[ -n "$entry" ]] && _print_row "REJECT" "$entry"; done

echo ""
echo "  Already in library: $ALREADY_KNOWN | Below quality floor: $SKIP_QUALITY | Cooldown: $SKIP_COOLDOWN"
echo "  ACCEPT: ${#SORTED_ACCEPTS[@]} | REJECT: ${#SORTED_REJECTS[@]}"

if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN complete — run without --dry-run to add accepted movies"
    exit 0
fi

if [[ "${#SORTED_ACCEPTS[@]}" -eq 0 ]]; then
    log "No movies above threshold — nothing to add"
    for entry in "${SORTED_REJECTS[@]}"; do
        [[ -z "$entry" ]] && continue
        IFS='|' read -r score rec_id title _ <<< "$entry"
        echo "REJECT|${rec_id}|${TODAY}|${title}" >> "$HISTORY_FILE" 2>/dev/null
    done
    exit 0
fi

# ==============================================================================================
# ━━━ Add to Radarr ━━━
# ==============================================================================================
echo ""
echo "━━━ $ICON_SYNC Adding to Radarr ━━━"

RADARR_ROOT=$(_radarr_get "rootfolder" | jq -r 'first(.[] | select(.accessible == true)) | .path' 2>/dev/null)
if [[ -z "$RADARR_ROOT" ]]; then error "Could not determine Radarr root folder"; exit 1; fi

QUALITY_ID=$(_radarr_get "qualityprofile" | jq -r '.[0].id' 2>/dev/null)
log "Root folder: $RADARR_ROOT | Quality profile: $QUALITY_ID"

ADDED=0
FAILED=0

for entry in "${SORTED_ACCEPTS[@]}"; do
    [[ -z "$entry" ]] && continue
    IFS='|' read -r score rec_id title seeds avg_int votes <<< "$entry"

    LOOKUP=$(_radarr_lookup "$rec_id")

    if [[ -z "$LOOKUP" ]] || echo "$LOOKUP" | jq -e '. == [] or . == null' >/dev/null 2>&1; then
        warn "  $ICON_WARN No match in Radarr lookup: $title (TMDB: $rec_id)"
        echo "FAIL|${rec_id}|${TODAY}|${title}" >> "$HISTORY_FILE" 2>/dev/null
        (( FAILED++ ))
        continue
    fi

    MOVIE_DATA=$(echo "$LOOKUP" | jq '.[0]' 2>/dev/null)
    RADARR_TITLE=$(echo "$MOVIE_DATA" | jq -r '.title // ""' 2>/dev/null)

    if [[ -z "$RADARR_TITLE" ]]; then
        warn "  $ICON_WARN Empty result for: $title"
        echo "FAIL|${rec_id}|${TODAY}|${title}" >> "$HISTORY_FILE" 2>/dev/null
        (( FAILED++ ))
        continue
    fi

    PAYLOAD=$(echo "$MOVIE_DATA" | jq \
        --arg root "$RADARR_ROOT" \
        --argjson qid "$QUALITY_ID" \
        '. + {
            rootFolderPath: $root,
            qualityProfileId: $qid,
            monitored: true,
            addOptions: {
                searchForMovie: false
            }
        }' 2>/dev/null)

    RESULT=$(_radarr_post "$PAYLOAD")

    if echo "$RESULT" | jq -e '.id' >/dev/null 2>&1; then
        MOVIE_ID=$(echo "$RESULT" | jq -r '.id')
        _radarr_command "{\"name\":\"MoviesSearch\",\"movieIds\":[${MOVIE_ID}]}" >/dev/null
        log "  $ICON_DONE Added: $RADARR_TITLE (score: $score | seeds: $seeds)"
        echo "ACCEPT|${rec_id}|${TODAY}|${RADARR_TITLE}" >> "$HISTORY_FILE" 2>/dev/null
        (( ADDED++ ))
    else
        warn "  $ICON_WARN Failed to add: $title"
        log "  $(echo "$RESULT" | head -c 200)"
        echo "FAIL|${rec_id}|${TODAY}|${title}" >> "$HISTORY_FILE" 2>/dev/null
        (( FAILED++ ))
    fi
done

for entry in "${SORTED_REJECTS[@]}"; do
    [[ -z "$entry" ]] && continue
    IFS='|' read -r score rec_id title _ <<< "$entry"
    echo "REJECT|${rec_id}|${TODAY}|${title}" >> "$HISTORY_FILE" 2>/dev/null
done

# ==============================================================================================
# ━━━ Summary ━━━
# ==============================================================================================
echo ""
echo "━━━━━ $ICON_SUMMARY DISCOVERY COMPLETE ━━━━━"
echo "  $ICON_DONE  Added:    $ADDED"
[[ "$FAILED" -gt 0 ]] && echo "  $ICON_WARN  Failed:   $FAILED"
echo "  $ICON_SKIP  Rejected: ${#SORTED_REJECTS[@]}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

[[ "$ADDED" -gt 0 ]] && notify \
    "$ADDED movie(s) added to Radarr via discovery on $(hostname)" \
    "Radarr Discovery" "normal"

exit 0
