import { useEffect } from 'react'
import { useQueryClient } from '@tanstack/react-query'
import { jellyfinClient, getMediaInfoApi } from '../api/jellyfin'
import { browserDeviceProfile } from '../lib/device-profile'
import type { BaseItemDto } from '../api/types'

/**
 * Pre-fire Jellyfin's PlaybackInfo handshake (and a tiny range request
 * against the resolved stream URL) when the user has been hovering a
 * card long enough that they're likely to play it. The handshake is
 * the longest sync part of opening playback, so cache-warming it makes
 * the click→playing transition feel near-instant.
 *
 * - Skips synthetic TMDB-only items (no real Jellyfin id).
 * - Idempotent per item: React Query dedups, so multiple armed cards
 *   pointing at the same id share one request.
 * - Best-effort: any error is swallowed silently; the player will
 *   re-issue PlaybackInfo as it normally does if the cache is missing.
 */
export function usePrebuffer(item: BaseItemDto | null | undefined, armed: boolean) {
  const qc = useQueryClient()
  const itemId = item?.Id
  const itemType = item?.Type

  useEffect(() => {
    if (!armed) return
    if (!itemId || String(itemId).startsWith('tmdb-')) return
    // Episodes / movies are the only item kinds that go through PlaybackInfo
    // for streaming; series / seasons would need a child resolution first.
    if (itemType !== 'Movie' && itemType !== 'Episode') return

    let cancelled = false

    const key = ['jellyfin', 'playback-info', itemId, undefined, undefined, undefined]
    qc.fetchQuery({
      queryKey: key,
      queryFn: async () => {
        const api = jellyfinClient.getApi()
        if (!api) return null
        const res = await getMediaInfoApi(api).getPostedPlaybackInfo({
          itemId,
          playbackInfoDto: {
            UserId: jellyfinClient.getAuthState()!.userId,
            MaxStreamingBitrate: 140_000_000,
            DeviceProfile: await browserDeviceProfile() as any,
            AutoOpenLiveStream: true,
            EnableDirectPlay: true,
            EnableDirectStream: true,
            EnableTranscoding: true,
            AllowVideoStreamCopy: true,
            AllowAudioStreamCopy: true,
          },
        })
        return res.data
      },
      staleTime: 60_000,
    }).then(playbackInfo => {
      if (cancelled || !playbackInfo) return
      const auth = jellyfinClient.getAuthState()
      if (!auth) return
      const source = playbackInfo.MediaSources?.[0]
      if (!source) return
      // Build the stream URL the way PlayerPage does and request the
      // first kilobyte. For direct-play this primes the HTTP cache; for
      // HLS transcodes this triggers Jellyfin to start the transcode
      // segment 0 ahead of time.
      const url = source.SupportsDirectPlay
        ? `${auth.serverUrl}/Videos/${itemId}/stream?static=true&MediaSourceId=${source.Id}&api_key=${auth.token}`
        : source.TranscodingUrl
          ? `${auth.serverUrl}${source.TranscodingUrl}`
          : null
      if (!url) return
      fetch(url, {
        method: 'GET',
        headers: { Range: 'bytes=0-32767' },
      }).catch(() => { /* warm-only; ignore */ })
    }).catch(() => { /* warm-only; ignore */ })

    return () => { cancelled = true }
  }, [armed, itemId, itemType, qc])
}
