import type { BaseItemDto } from '../api/types'
import type { TmdbEpisodeGroupFull } from '../api/tmdb'

/**
 * TMDB episode group types per their docs. We surface the ones with the
 * most user value as alternative orderings; aired (1) is the natural
 * order and rendered without a group reorder.
 */
export const EPISODE_GROUP_TYPES: Record<number, string> = {
  1: 'Original air',
  2: 'Absolute',
  3: 'DVD',
  4: 'Digital',
  5: 'Story arc',
  6: 'Production',
  7: 'TV',
}

export interface OrderingOption {
  /** TMDB group id, or 'aired' for the unmodified Jellyfin sequence. */
  id: string
  label: string
  description?: string
}

/**
 * Reorder a Jellyfin episode list to match a TMDB episode-group ordering.
 *
 * Strategy: build a Map from `${season}:${episode}` -> position in the
 * group. Episodes the group references go first in the group's order;
 * episodes not in the group fall to the end in their original order so
 * we never silently drop entries.
 */
export function applyEpisodeGroupOrder(
  episodes: BaseItemDto[],
  group: TmdbEpisodeGroupFull | null | undefined,
): BaseItemDto[] {
  if (!group || !episodes.length) return episodes
  const positionByKey = new Map<string, number>()
  let pos = 0
  for (const g of group.groups || []) {
    for (const ep of g.episodes) {
      const key = `${ep.season_number}:${ep.episode_number}`
      if (!positionByKey.has(key)) positionByKey.set(key, pos++)
    }
  }
  if (positionByKey.size === 0) return episodes
  const tagged = episodes.map((ep, originalIndex) => {
    const key = `${ep.ParentIndexNumber ?? -1}:${ep.IndexNumber ?? -1}`
    const groupPos = positionByKey.get(key)
    return { ep, groupPos, originalIndex }
  })
  return tagged
    .sort((a, b) => {
      if (a.groupPos == null && b.groupPos == null) {
        return a.originalIndex - b.originalIndex
      }
      if (a.groupPos == null) return 1
      if (b.groupPos == null) return -1
      return a.groupPos - b.groupPos
    })
    .map(t => t.ep)
}
