import { useNavigate } from 'react-router-dom'
import { motion } from 'framer-motion'
import { User, Clock, Calendar, Star, Disc3, Music, FileVideo } from '../../lib/icons'
import { getBestImage, getStoredServerUrl } from '../../api/jellyfin'
import { getTmdbImageUrl } from '../../api/tmdb'
import { formatRuntime } from '../../lib/format'
import { usePosterGridClasses } from '../../lib/density'
import PosterCard from '../../components/ui/PosterCard'
import type { BaseItemDto } from '../../api/types'

export function SectionHeader({
  label,
  hint,
  count,
}: { label: string; hint?: string; count?: number }) {
  return (
    <div className="flex items-baseline justify-between mb-4">
      <div className="flex items-baseline gap-3">
        <h2 className="text-[11px] font-semibold text-text-2 uppercase tracking-[0.14em]">
          {label}
        </h2>
        {hint && <span className="text-[11px] text-text-4">{hint}</span>}
      </div>
      {count != null && (
        <span className="text-[11px] text-text-4 tabular-nums">{count}</span>
      )}
    </div>
  )
}

interface TmdbPerson {
  id: number
  name?: string
  profile_path?: string | null
  known_for_department?: string
  known_for?: Array<{ title?: string; name?: string }>
}

export function PeopleSection({ people }: { people: TmdbPerson[] }) {
  const navigate = useNavigate()
  return (
    <section>
      <SectionHeader label="People" count={people.length} />
      <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-x-5 gap-y-7">
        {people.map((p, i) => {
          const knownFor = (p.known_for || [])
            .slice(0, 2)
            .map(k => k.title || k.name)
            .filter(Boolean)
            .join(', ')
          return (
            <motion.button
              key={p.id}
              onClick={() => navigate(`/person/${p.id}`)}
              initial={{ opacity: 0, y: 6 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.24, delay: Math.min(i * 0.025, 0.2), ease: [0.16, 1, 0.3, 1] }}
              className="group flex items-center gap-4 p-2.5 -mx-2.5 rounded-xl hover:bg-elevated/50 transition-colors duration-200 text-left focus-ring"
            >
              <div className="relative w-20 h-20 rounded-full overflow-hidden bg-elevated shrink-0 ring-1 ring-border group-hover:ring-accent/40 transition-shadow duration-200">
                {p.profile_path ? (
                  <img
                    src={getTmdbImageUrl(p.profile_path, 'w185')}
                    alt={p.name}
                    className="w-full h-full object-cover"
                    loading="lazy"
                  />
                ) : (
                  <div className="w-full h-full grid place-items-center bg-gradient-to-br from-elevated to-surface">
                    <User size={26} className="text-text-4" />
                  </div>
                )}
              </div>
              <div className="min-w-0 flex-1">
                <p className="font-display text-[15px] text-text-1 font-semibold truncate tracking-tight">
                  {p.name}
                </p>
                {p.known_for_department && (
                  <p className="text-[11px] text-text-3 mt-0.5">
                    {p.known_for_department}
                  </p>
                )}
                {knownFor && (
                  <p className="text-[12px] text-text-4 mt-1 line-clamp-2 leading-snug">
                    {knownFor}
                  </p>
                )}
              </div>
            </motion.button>
          )
        })}
      </div>
    </section>
  )
}

export function MoviesShowsSection({
  cards,
  localCount,
  tmdbExtraCount,
}: { cards: BaseItemDto[]; localCount: number; tmdbExtraCount: number }) {
  const navigate = useNavigate()
  const grid = usePosterGridClasses()
  const hint =
    localCount && tmdbExtraCount
      ? `${localCount} in your library, ${tmdbExtraCount} on TMDB`
      : localCount
        ? `${localCount} in your library`
        : tmdbExtraCount
          ? `${tmdbExtraCount} on TMDB`
          : undefined
  return (
    <section>
      <SectionHeader label="Movies & TV" hint={hint} count={cards.length} />
      <div className={grid}>
        {cards.map((item, i) => (
          <motion.div
            key={item.Id || i}
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.32, delay: Math.min(i * 0.025, 0.2), ease: [0.16, 1, 0.3, 1] }}
          >
            <PosterCard
              item={item}
              priority={i < 6}
              onClick={() => item.Id && navigate(`/item/${item.Id}`)}
            />
          </motion.div>
        ))}
      </div>
    </section>
  )
}

export function EpisodesSection({ items }: { items: BaseItemDto[] }) {
  const navigate = useNavigate()
  const serverUrl = getStoredServerUrl()

  return (
    <section>
      <SectionHeader label="Episodes" count={items.length} />
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-3">
        {items.map((ep, i) => {
          // Episode still lives in the Primary image type for Episodes;
          // Thumb is rarely populated. Try Primary first, fall back to
          // backdrop (which falls back to parent series), then thumb.
          const thumb =
            getBestImage(serverUrl, ep, 'primary', 480) ||
            getBestImage(serverUrl, ep, 'backdrop', 480) ||
            getBestImage(serverUrl, ep, 'thumb', 480) ||
            ''
          const seasonEp =
            ep.ParentIndexNumber != null && ep.IndexNumber != null
              ? `S${String(ep.ParentIndexNumber).padStart(2, '0')}E${String(ep.IndexNumber).padStart(2, '0')}`
              : ''
          const seriesName = ep.SeriesName || ''
          const runtime = ep.RunTimeTicks ? formatRuntime(ep.RunTimeTicks) : ''
          return (
            <motion.button
              key={ep.Id || i}
              onClick={() => ep.Id && navigate(`/item/${ep.Id}`)}
              initial={{ opacity: 0, y: 6 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.26, delay: Math.min(i * 0.02, 0.2), ease: [0.16, 1, 0.3, 1] }}
              className="group flex items-stretch gap-4 p-2.5 rounded-xl bg-elevated/40 ring-1 ring-border hover:ring-border-strong hover:bg-elevated/70 transition-all duration-200 text-left focus-ring"
            >
              <div className="relative w-[144px] aspect-video rounded-md overflow-hidden bg-black shrink-0 ring-1 ring-border">
                {thumb ? (
                  <img src={thumb} alt="" className="w-full h-full object-cover" loading="lazy" />
                ) : (
                  <div className="w-full h-full grid place-items-center text-text-4">
                    <FileVideo size={22} />
                  </div>
                )}
                {seasonEp && (
                  <span className="absolute top-1.5 left-1.5 inline-flex items-center h-[18px] px-1.5 rounded text-[10px] font-bold tracking-wider uppercase bg-black/70 text-white backdrop-blur-sm tabular-nums">
                    {seasonEp}
                  </span>
                )}
              </div>
              <div className="min-w-0 flex-1 flex flex-col py-0.5">
                {seriesName && (
                  <p className="text-[11px] uppercase tracking-[0.12em] text-text-3 truncate font-semibold">
                    {seriesName}
                  </p>
                )}
                <p className="text-[14px] text-text-1 font-medium truncate mt-0.5 tracking-tight">
                  {ep.Name || 'Untitled'}
                </p>
                <div className="mt-auto flex items-center gap-3 text-[11.5px] text-text-3 tabular-nums">
                  {runtime && (
                    <span className="inline-flex items-center gap-1">
                      <Clock size={11} className="text-text-4" /> {runtime}
                    </span>
                  )}
                  {ep.ProductionYear && (
                    <span className="inline-flex items-center gap-1">
                      <Calendar size={11} className="text-text-4" /> {ep.ProductionYear}
                    </span>
                  )}
                  {typeof ep.CommunityRating === 'number' && (
                    <span className="inline-flex items-center gap-1">
                      <Star size={11} className="text-accent" />
                      {ep.CommunityRating.toFixed(1)}
                    </span>
                  )}
                </div>
              </div>
            </motion.button>
          )
        })}
      </div>
    </section>
  )
}

export function MusicSection({
  albums,
  artists,
  tracks,
}: { albums: BaseItemDto[]; artists: BaseItemDto[]; tracks: BaseItemDto[] }) {
  return (
    <section className="space-y-10">
      {artists.length > 0 && <MusicGrid label="Artists" items={artists} circular icon={User} />}
      {albums.length > 0 && <MusicGrid label="Albums" items={albums} icon={Disc3} />}
      {tracks.length > 0 && <TrackList items={tracks} />}
    </section>
  )
}

function MusicGrid({
  label,
  items,
  circular,
  icon: Icon,
}: {
  label: string
  items: BaseItemDto[]
  circular?: boolean
  icon: typeof User
}) {
  const navigate = useNavigate()
  const serverUrl = getStoredServerUrl()
  return (
    <div>
      <SectionHeader label={label} count={items.length} />
      <div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-7 gap-4 gap-y-6">
        {items.map((item, i) => {
          const img = getBestImage(serverUrl, item, 'primary', 240)
          const augmented = item as BaseItemDto & { AlbumArtist?: string; Artists?: string[] }
          const subtitle =
            augmented.AlbumArtist ||
            (Array.isArray(augmented.Artists) ? augmented.Artists.slice(0, 2).join(', ') : '') ||
            ''
          return (
            <motion.button
              key={item.Id || i}
              onClick={() => item.Id && navigate(`/item/${item.Id}`)}
              initial={{ opacity: 0, y: 8 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.28, delay: Math.min(i * 0.025, 0.2), ease: [0.16, 1, 0.3, 1] }}
              className="group text-left focus-ring rounded-lg"
            >
              <div
                className={`relative aspect-square overflow-hidden bg-elevated ring-1 ring-border group-hover:ring-border-strong transition-shadow duration-200 ${
                  circular ? 'rounded-full' : 'rounded-lg'
                }`}
              >
                {img ? (
                  <img src={img} alt="" className="w-full h-full object-cover" loading="lazy" />
                ) : (
                  <div className="w-full h-full grid place-items-center bg-gradient-to-br from-elevated to-surface">
                    <Icon size={28} className="text-text-4" />
                  </div>
                )}
              </div>
              <p className="mt-2.5 text-[13px] text-text-1 font-medium truncate tracking-tight">
                {item.Name || 'Untitled'}
              </p>
              {subtitle && (
                <p className="text-[11.5px] text-text-3 truncate mt-0.5">{subtitle}</p>
              )}
            </motion.button>
          )
        })}
      </div>
    </div>
  )
}

function TrackList({ items }: { items: BaseItemDto[] }) {
  const navigate = useNavigate()
  const serverUrl = getStoredServerUrl()
  return (
    <div>
      <SectionHeader label="Tracks" count={items.length} />
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
        {items.map((item, i) => {
          const img = getBestImage(serverUrl, item, 'primary', 96)
          const augmented = item as BaseItemDto & { AlbumArtist?: string; Artists?: string[]; Album?: string }
          const sub = [
            augmented.AlbumArtist || (Array.isArray(augmented.Artists) ? augmented.Artists[0] : ''),
            augmented.Album,
          ].filter(Boolean).join(' - ')
          const runtime = item.RunTimeTicks ? formatRuntime(item.RunTimeTicks) : ''
          return (
            <motion.button
              key={item.Id || i}
              onClick={() => item.Id && navigate(`/item/${item.Id}`)}
              initial={{ opacity: 0, y: 4 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.22, delay: Math.min(i * 0.02, 0.2), ease: [0.16, 1, 0.3, 1] }}
              className="group flex items-center gap-3 p-2 rounded-lg hover:bg-elevated/60 transition-colors duration-150 text-left focus-ring"
            >
              <div className="w-11 h-11 rounded-md overflow-hidden bg-elevated shrink-0 ring-1 ring-border grid place-items-center">
                {img ? (
                  <img src={img} alt="" className="w-full h-full object-cover" loading="lazy" />
                ) : (
                  <Music size={16} className="text-text-3" />
                )}
              </div>
              <div className="flex-1 min-w-0">
                <p className="text-[13.5px] text-text-1 truncate font-medium tracking-tight">
                  {item.Name || 'Untitled'}
                </p>
                {sub && <p className="text-[11.5px] text-text-3 truncate">{sub}</p>}
              </div>
              {runtime && (
                <span className="text-[11px] text-text-4 tabular-nums shrink-0">{runtime}</span>
              )}
            </motion.button>
          )
        })}
      </div>
    </div>
  )
}
