import type { MediaItem } from './ipc'

/**
 * Retention / quality-upgrade selection (PINCHFLAT stretch). Pure so the choice
 * of which items to prune or re-download is unit-tested with an injected `now`
 * and no filesystem — the impure half (deleting files, re-enqueuing) lives in
 * the caller.
 */

export interface PrunePolicy {
  /** keep only items downloaded within the last N days; older ones are pruned */
  maxAgeDays?: number
  /** keep only the N most-recently-downloaded items; older ones are pruned */
  maxCount?: number
}

/**
 * Which downloaded items a prune policy would remove. An item is a candidate
 * when it's downloaded, has a real file on disk to delete, AND falls outside
 * EITHER limit (age or count) — the two combine as "keep if it passes both".
 * Ordered newest-first internally so `maxCount` keeps the freshest.
 *
 * Returns the items to prune (delete file + clear downloaded state). Never
 * touches un-downloaded items or ones with no filePath. Both limits omitted =
 * nothing pruned (retention off).
 */
export function selectPruneCandidates(
  items: MediaItem[],
  policy: PrunePolicy,
  now: number
): MediaItem[] {
  const { maxAgeDays, maxCount } = policy
  if (maxAgeDays == null && maxCount == null) return []

  // Only downloaded items with a file are prunable; newest-first for the count cut.
  const prunable = items
    .filter((i) => i.downloaded && i.filePath && typeof i.downloadedAt === 'number')
    .sort((a, b) => (b.downloadedAt ?? 0) - (a.downloadedAt ?? 0))

  const ageCutoff = maxAgeDays != null ? now - maxAgeDays * 86_400_000 : null

  return prunable.filter((item, index) => {
    const tooOld = ageCutoff != null && (item.downloadedAt ?? 0) < ageCutoff
    const overCount = maxCount != null && index >= maxCount
    return tooOld || overCount
  })
}

/**
 * Which downloaded items were fetched at a quality BELOW the source's current
 * target, so they're worth re-downloading to upgrade. `qualityRank` maps a
 * quality label to a comparable number (higher = better); an item ranks below
 * target when its recorded `downloadedQuality` ranks lower than `targetQuality`.
 *
 * An item with no recorded `downloadedQuality` (downloaded before this was
 * tracked) is NOT selected — we can't prove it's below target, and re-downloading
 * on a guess would churn. Only downloaded items are considered.
 */
export function selectUpgradeCandidates(
  items: MediaItem[],
  targetQuality: string,
  qualityRank: (label: string) => number
): MediaItem[] {
  const target = qualityRank(targetQuality)
  return items.filter(
    (i) =>
      i.downloaded &&
      typeof i.downloadedQuality === 'string' &&
      qualityRank(i.downloadedQuality) < target
  )
}
