import { useState, useEffect } from 'react'
import useEmblaCarousel from 'embla-carousel-react'
import { ChevronLeft, ChevronRight, ArrowRight, Library, List, ListDetails } from '../../lib/icons'
import { motion, AnimatePresence } from 'framer-motion'
import type { BaseItemDto } from '../../api/types'
import PosterCard from './PosterCard'
import { useNavigate } from 'react-router-dom'
import { getBestImage, getStoredServerUrl } from '../../api/jellyfin'
import { useQuickLookStore } from '../../stores/quick-look-store'
import { formatRuntime } from '../../lib/format'

type Layout = 'poster' | 'backdrop' | 'list'

interface Props {
  title: string
  subtitle?: string
  items: BaseItemDto[]
  aspect?: 'poster' | 'landscape' | 'square'
  loading?: boolean
  seeAllHref?: string
  /** Persist a non-default layout under this key. Defaults to title. */
  layoutKey?: string
}

function readSavedLayout(key: string, fallback: Layout): Layout {
  if (typeof window === 'undefined') return fallback
  const v = localStorage.getItem(`row_layout:${key}`)
  if (v === 'poster' || v === 'backdrop' || v === 'list') return v
  return fallback
}

function SkeletonCards({
  count = 8,
  aspect = 'poster',
  width,
}: {
  count?: number
  aspect?: 'poster' | 'landscape' | 'square'
  width: string
}) {
  const aspectClass = aspect === 'poster' ? 'aspect-[2/3]' : aspect === 'square' ? 'aspect-square' : 'aspect-video'
  return (
    <>
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} className={`shrink-0 ${width}`}>
          <div className={`skeleton ${aspectClass} rounded-lg`} />
          <div className="mt-2 space-y-1.5">
            <div className="skeleton h-3 w-3/4 rounded" />
            <div className="skeleton h-2.5 w-1/2 rounded" />
          </div>
        </div>
      ))}
    </>
  )
}

export default function ContentRow({ title, subtitle, items, aspect = 'poster', loading, seeAllHref, layoutKey }: Props) {
  // Map the legacy `aspect` prop onto the new `layout` model. Landscape
  // rows default to 'backdrop' so existing call sites keep their look.
  const defaultLayout: Layout = aspect === 'landscape' ? 'backdrop' : 'poster'
  const persistKey = layoutKey || title
  const [layout, setLayoutState] = useState<Layout>(() => readSavedLayout(persistKey, defaultLayout))
  const setLayout = (next: Layout) => {
    setLayoutState(next)
    try { localStorage.setItem(`row_layout:${persistKey}`, next) } catch { /* noop */ }
  }
  const effectiveAspect: 'poster' | 'landscape' | 'square' =
    layout === 'backdrop' ? 'landscape' : layout === 'poster' ? (aspect === 'square' ? 'square' : 'poster') : 'poster'

  const [ref, embla] = useEmblaCarousel({
    align: 'start',
    containScroll: 'trimSnaps',
    dragFree: true,
  })
  const [canScrollPrev, setCanScrollPrev] = useState(false)
  const [canScrollNext, setCanScrollNext] = useState(false)
  const navigate = useNavigate()

  useEffect(() => {
    if (!embla) return
    const update = () => {
      setCanScrollPrev(embla.canScrollPrev())
      setCanScrollNext(embla.canScrollNext())
    }
    embla.on('select', update)
    embla.on('reInit', update)
    embla.on('scroll', update)
    update()
    return () => {
      embla.off('select', update)
      embla.off('reInit', update)
      embla.off('scroll', update)
    }
  }, [embla])

  const widthClass =
    effectiveAspect === 'poster' ? 'w-[160px]'
    : effectiveAspect === 'square' ? 'w-[180px]'
    : 'w-[280px]'

  const showHeader = !!title || !!subtitle || !!seeAllHref

  return (
    <section className="mb-10" style={{ contentVisibility: 'auto', containIntrinsicHeight: '300px' }}>
      {/* Row header */}
      {showHeader && (
      <div className="flex items-end justify-between mb-3.5 px-7 gap-3">
        <div className="min-w-0">
          {title && <h2 className="text-[18px] font-semibold text-text-1 tracking-tight">{title}</h2>}
          {subtitle && (
            <p className="text-[12px] text-text-3 mt-0.5">{subtitle}</p>
          )}
        </div>
        <div className="flex items-center gap-3 shrink-0">
          <LayoutSwitcher value={layout} onChange={setLayout} />
          {seeAllHref && (
            <button
              onClick={() => navigate(seeAllHref)}
              className="group flex items-center gap-1 text-[12px] text-text-3 hover:text-accent transition-colors duration-200 px-2 -mr-2 py-1 focus-ring rounded"
            >
              See all
              <ArrowRight
                size={12}
                className="transition-transform duration-200 group-hover:translate-x-0.5"
              />
            </button>
          )}
        </div>
      </div>
      )}

      {/* List layout - vertical stack, no carousel */}
      {layout === 'list' && !loading && (
        <div className="px-7 space-y-2">
          {items.slice(0, 12).map((item, i) => (
            <ListRowCard key={item.Id} item={item} index={i} />
          ))}
          {items.length > 12 && (
            <button
              onClick={() => seeAllHref && navigate(seeAllHref)}
              disabled={!seeAllHref}
              className="w-full text-[12px] text-text-3 hover:text-accent py-2 transition disabled:opacity-50"
            >
              {seeAllHref ? `Show all ${items.length}` : `+${items.length - 12} more`}
            </button>
          )}
        </div>
      )}
      {layout !== 'list' && (
      <>

      {/* Carousel with edge fades + nav arrows */}
      <div className="relative group/row">
        {/* Edge fade left */}
        <div
          className={`absolute left-0 top-0 bottom-0 w-12 z-10 pointer-events-none bg-gradient-to-r from-void via-void/60 to-transparent transition-opacity duration-300 ${
            canScrollPrev ? 'opacity-100' : 'opacity-0'
          }`}
        />
        {/* Edge fade right */}
        <div
          className={`absolute right-0 top-0 bottom-0 w-12 z-10 pointer-events-none bg-gradient-to-l from-void via-void/60 to-transparent transition-opacity duration-300 ${
            canScrollNext ? 'opacity-100' : 'opacity-0'
          }`}
        />

        {/* Prev */}
        <AnimatePresence>
          {canScrollPrev && (
            <motion.button
              initial={{ opacity: 0, x: 4 }}
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: 4 }}
              transition={{ duration: 0.18 }}
              onClick={() => embla?.scrollPrev()}
              className="absolute left-2 top-0 bottom-12 w-12 z-20 flex items-center justify-center opacity-0 group-hover/row:opacity-100 transition-opacity duration-200 focus:opacity-100"
              aria-label="Previous"
            >
              <div className="w-9 h-9 rounded-full glass-strong border border-border-hover grid place-items-center text-text-2 hover:text-accent shadow-md hover:scale-105 active:scale-95 transition-all duration-200">
                <ChevronLeft size={16} strokeWidth={2.25} />
              </div>
            </motion.button>
          )}
        </AnimatePresence>

        {/* Next */}
        <AnimatePresence>
          {canScrollNext && (
            <motion.button
              initial={{ opacity: 0, x: -4 }}
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: -4 }}
              transition={{ duration: 0.18 }}
              onClick={() => embla?.scrollNext()}
              className="absolute right-2 top-0 bottom-12 w-12 z-20 flex items-center justify-center opacity-0 group-hover/row:opacity-100 transition-opacity duration-200 focus:opacity-100"
              aria-label="Next"
            >
              <div className="w-9 h-9 rounded-full glass-strong border border-border-hover grid place-items-center text-text-2 hover:text-accent shadow-md hover:scale-105 active:scale-95 transition-all duration-200">
                <ChevronRight size={16} strokeWidth={2.25} />
              </div>
            </motion.button>
          )}
        </AnimatePresence>

        {/* Track */}
        <div ref={ref} className="overflow-hidden">
          <div className="flex gap-3 px-7 py-1">
            {loading ? (
              <SkeletonCards aspect={aspect} width={widthClass} />
            ) : (
              items.map((item, i) => (
                <motion.div
                  key={item.Id}
                  initial={{ opacity: 0, y: 12 }}
                  animate={{ opacity: 1, y: 0 }}
                  transition={{
                    duration: 0.4,
                    delay: Math.min(i * 0.025, 0.4),
                    ease: [0.16, 1, 0.3, 1],
                  }}
                  className={`shrink-0 ${widthClass}`}
                >
                  <PosterCard
                    item={item}
                    aspect={effectiveAspect}
                    priority={i < 6}
                    onClick={() => item.Id && navigate(`/item/${item.Id}`)}
                  />
                </motion.div>
              ))
            )}
          </div>
        </div>
      </div>
      </>
      )}
    </section>
  )
}

function LayoutSwitcher({ value, onChange }: { value: Layout; onChange: (l: Layout) => void }) {
  const opts: Array<{ k: Layout; label: string; Icon: typeof List }> = [
    { k: 'poster', label: 'Posters', Icon: ListDetails },
    { k: 'backdrop', label: 'Backdrops', Icon: Library },
    { k: 'list', label: 'List', Icon: List },
  ]
  return (
    <div className="hidden md:flex items-center gap-0.5 bg-elevated/40 ring-1 ring-border rounded-md p-0.5">
      {opts.map(o => {
        const on = value === o.k
        return (
          <button
            key={o.k}
            onClick={() => onChange(o.k)}
            aria-label={o.label}
            title={o.label}
            className={`w-7 h-7 grid place-items-center rounded transition focus-ring ${
              on ? 'bg-accent/15 text-accent ring-1 ring-accent/30' : 'text-text-3 hover:text-text-1'
            }`}
          >
            <o.Icon size={13} stroke={2} />
          </button>
        )
      })}
    </div>
  )
}

function ListRowCard({ item, index }: { item: BaseItemDto; index: number }) {
  const navigate = useNavigate()
  const openQuickLook = useQuickLookStore(s => s.open)
  const serverUrl = getStoredServerUrl()
  const thumb =
    getBestImage(serverUrl, item, 'thumb', 240) ||
    getBestImage(serverUrl, item, 'primary', 200) ||
    item._tmdbPoster ||
    null
  const subtitle = [
    item.ProductionYear,
    item.RunTimeTicks ? formatRuntime(item.RunTimeTicks) : '',
    (item.Genres || []).slice(0, 2).join(', '),
  ].filter(Boolean).join(' · ')
  return (
    <motion.button
      initial={{ opacity: 0, y: 4 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.25, delay: Math.min(index * 0.02, 0.25) }}
      onClick={() => item.Id && navigate(`/item/${item.Id}`)}
      onContextMenu={e => { e.preventDefault(); openQuickLook(item) }}
      className="w-full flex items-center gap-3 p-2 rounded-lg bg-elevated/40 ring-1 ring-border hover:ring-border-strong hover:bg-elevated/70 transition text-left focus-ring"
    >
      <div className="shrink-0 w-[88px] aspect-video rounded bg-black overflow-hidden ring-1 ring-border">
        {thumb && <img src={thumb} alt="" className="w-full h-full object-cover" loading="lazy" />}
      </div>
      <div className="min-w-0 flex-1">
        <p className="text-[13px] font-medium text-text-1 truncate tracking-tight">
          {item.Name || 'Untitled'}
        </p>
        {subtitle && (
          <p className="text-[11px] text-text-3 truncate mt-0.5">{subtitle}</p>
        )}
        {item.Overview && (
          <p className="text-[11px] text-text-4 truncate mt-0.5 hidden sm:block">{item.Overview}</p>
        )}
      </div>
    </motion.button>
  )
}
