import { useMemo } from 'react'
import { useQueries } from '@tanstack/react-query'
import { getMovieFull, getTvShowFull } from '../api/tmdb'
import type { BaseItemDto } from '../api/types'

const STALE = 24 * 60 * 60 * 1000

export interface PersonSpotlight {
  id: number
  name: string
  profile_path: string | null
  /** Library item ids that contributed to this person's tally. */
  contributingItemIds: string[]
  /** Aggregate count - cast/director appearances among watched items. */
  count: number
}

/**
 * Aggregates directors and lead actors across a user's recently
 * watched items, returning the persons who appear at least twice.
 *
 * Implementation: batch-fetches TMDB full-credits for the top-N most
 * recently watched items via React Query's `useQueries`. Both director
 * (crew.job === 'Director') and top-billed cast (first 5) are tallied.
 *
 * Capped at `limit` items to keep the home page request burst small.
 */
export function usePersonSpotlights(
  recent: BaseItemDto[] | null | undefined,
  limit = 8,
) {
  const seeds = useMemo(() => {
    if (!recent) return [] as Array<{ tmdbId: number; type: 'movie' | 'tv'; itemId: string }>
    const out: Array<{ tmdbId: number; type: 'movie' | 'tv'; itemId: string }> = []
    for (const it of recent) {
      const t = it.ProviderIds?.Tmdb
      if (!t || !it.Id) continue
      const tmdbId = Number(t)
      if (!Number.isFinite(tmdbId)) continue
      const type: 'movie' | 'tv' = it.Type === 'Series' ? 'tv' : 'movie'
      out.push({ tmdbId, type, itemId: it.Id })
      if (out.length >= limit) break
    }
    return out
  }, [recent, limit])

  const queries = useQueries({
    queries: seeds.map(s => ({
      queryKey: ['tmdb', s.type === 'tv' ? 'tv-full' : 'movie-full', s.tmdbId],
      queryFn: () =>
        s.type === 'tv' ? getTvShowFull(s.tmdbId) : getMovieFull(s.tmdbId),
      staleTime: STALE,
    })),
  })

  return useMemo(() => {
    const directorMap = new Map<number, PersonSpotlight & { profile_path: string | null }>()
    const actorMap = new Map<number, PersonSpotlight & { profile_path: string | null }>()

    seeds.forEach((seed, i) => {
      const data: any = queries[i]?.data
      if (!data) return
      const credits = data.credits
      if (!credits) return

      const directors = (credits.crew || []).filter((c: any) => c.job === 'Director')
      for (const d of directors) {
        const cur = directorMap.get(d.id)
        if (cur) {
          cur.count += 1
          if (!cur.contributingItemIds.includes(seed.itemId)) {
            cur.contributingItemIds.push(seed.itemId)
          }
        } else {
          directorMap.set(d.id, {
            id: d.id,
            name: d.name,
            profile_path: d.profile_path,
            count: 1,
            contributingItemIds: [seed.itemId],
          })
        }
      }

      // Top 5 billed cast members per item; deeper than that is mostly
      // ensemble noise that distorts the recommendation.
      const billed = (credits.cast || []).slice(0, 5)
      for (const c of billed) {
        const cur = actorMap.get(c.id)
        if (cur) {
          cur.count += 1
          if (!cur.contributingItemIds.includes(seed.itemId)) {
            cur.contributingItemIds.push(seed.itemId)
          }
        } else {
          actorMap.set(c.id, {
            id: c.id,
            name: c.name,
            profile_path: c.profile_path,
            count: 1,
            contributingItemIds: [seed.itemId],
          })
        }
      }
    })

    const topDirector = [...directorMap.values()]
      .filter(d => d.count >= 2)
      .sort((a, b) => b.count - a.count)[0] || null

    const topActor = [...actorMap.values()]
      .filter(a => a.count >= 2)
      // Avoid actor === director collision so we don't render the same
      // person twice on the home page.
      .filter(a => a.id !== topDirector?.id)
      .sort((a, b) => b.count - a.count)[0] || null

    return {
      director: topDirector,
      actor: topActor,
      isLoading: queries.some(q => q.isLoading),
    }
  }, [seeds, queries])
}
