/**
 * Renders a Jellyfin trickplay thumbnail for a given playback time. Jellyfin
 * stores trickplay frames as a sprite sheet ("tile") - one image containing
 * many small thumbnails in a grid. The tile's metadata (frame size, tile
 * dimensions, interval, count) lives on `item.Trickplay`. We compute which
 * tile + which cell within the tile corresponds to the requested second,
 * then position a fixed-size box over the right cell with `background-image`
 * + `background-position`.
 *
 * The component returns null silently if trickplay isn't generated for the
 * source - that's the most common case when nothing was processed yet.
 */

interface TrickplayInfo {
  Width: number
  Height: number
  TileWidth: number
  TileHeight: number
  ThumbnailCount: number
  Interval: number // ms between frames
  Bandwidth?: number
}

interface Props {
  item: any
  serverUrl: string
  token: string
  timeSec: number
  /** Visible width on screen. Aspect ratio is preserved off the source frame. */
  displayWidth?: number
}

/**
 * Picks the highest-resolution trickplay variant the server has, across all
 * media sources. Jellyfin keys them by MediaSourceId, then by source width
 * in pixels (e.g. "320", "640"). Larger wins when present.
 */
function pickBestVariant(
  trickplay: any,
): { mediaSourceId: string; info: TrickplayInfo; widthKey: string } | null {
  if (!trickplay || typeof trickplay !== 'object') return null
  let best: { mediaSourceId: string; info: TrickplayInfo; widthKey: string } | null = null
  for (const mediaSourceId of Object.keys(trickplay)) {
    const variants = trickplay[mediaSourceId]
    if (!variants || typeof variants !== 'object') continue
    for (const widthKey of Object.keys(variants)) {
      const info = variants[widthKey] as TrickplayInfo
      if (!info?.Width || !info?.Height || !info?.TileWidth || !info?.TileHeight) continue
      const w = Number(widthKey)
      if (!best || w > Number(best.widthKey)) {
        best = { mediaSourceId, info, widthKey }
      }
    }
  }
  return best
}

export default function TrickplayThumbnail({
  item,
  serverUrl,
  token,
  timeSec,
  displayWidth = 200,
}: Props) {
  const variant = pickBestVariant(item?.Trickplay)
  if (!variant || !item?.Id) return null
  const { info, widthKey } = variant
  const itemId = item.Id as string

  const tilesPerSheet = info.TileWidth * info.TileHeight
  const thumbIndex = Math.max(
    0,
    Math.min(info.ThumbnailCount - 1, Math.floor((timeSec * 1000) / info.Interval)),
  )
  const tileIndex = Math.floor(thumbIndex / tilesPerSheet)
  const positionInTile = thumbIndex % tilesPerSheet
  const col = positionInTile % info.TileWidth
  const row = Math.floor(positionInTile / info.TileWidth)

  const tileUrl = `${serverUrl}/Videos/${itemId}/Trickplay/${widthKey}/${tileIndex}.jpg?api_key=${encodeURIComponent(
    token,
  )}`

  const aspectRatio = info.Width / info.Height
  const displayHeight = displayWidth / aspectRatio
  const scale = displayWidth / info.Width

  return (
    <div
      className="rounded-md ring-1 ring-white/15 shadow-2xl bg-black"
      style={{
        width: `${displayWidth}px`,
        height: `${displayHeight}px`,
        backgroundImage: `url("${tileUrl}")`,
        backgroundSize: `${info.Width * info.TileWidth * scale}px ${info.Height * info.TileHeight * scale}px`,
        backgroundPosition: `-${col * info.Width * scale}px -${row * info.Height * scale}px`,
        backgroundRepeat: 'no-repeat',
      }}
    />
  )
}
