import { Suspense, useState, type ComponentType } from 'react'
import { NavLink, Outlet } from 'react-router-dom'
import { motion, LayoutGroup, AnimatePresence } from 'framer-motion'
import * as Tooltip from '@radix-ui/react-tooltip'
import {
  Home,
  Film,
  Tv,
  Search,
  Compass,
  Settings,
  LogOut,
  Playlists,
  User,
  Database,
  Activity,
  Radio,
  Download,
} from '../../lib/icons'
import type { AuthState } from '../../api/types'
import AppHeader from './AppHeader'
import MiniPlayer from '../player/MiniPlayer'
import NowPlaying from '../player/NowPlaying'
import OfflineBanner from '../ui/OfflineBanner'
import QuickLookModal from '../ui/QuickLookModal'
import YoutubeViewerModal from '../ui/YoutubeViewerModal'
import RequestModal from '../request/RequestModal'
import ToastHost from '../ui/ToastHost'
import { useRequestModal } from '../../stores/request-modal-store'
import {
  useSidebarStore,
  SIDEBAR_COLLAPSED_W,
  SIDEBAR_DEFAULT_W,
  SIDEBAR_MIN_W,
  SIDEBAR_MAX_W,
} from '../../stores/sidebar-store'

interface NavItem {
  to: string
  icon: ComponentType<{ size?: number; stroke?: number; className?: string }>
  label: string
  kbd?: string
}

interface NavSection {
  label: string
  items: NavItem[]
}

const NAV_SECTIONS: NavSection[] = [
  {
    label: 'Library',
    items: [
      { to: '/', icon: Home, label: 'Home' },
      { to: '/movies', icon: Film, label: 'Movies' },
      { to: '/shows', icon: Tv, label: 'Shows' },
      { to: '/playlists', icon: Playlists, label: 'Playlists' },
      { to: '/live', icon: Radio, label: 'Live TV' },
      { to: '/requests', icon: Database, label: 'Requests' },
      { to: '/downloads', icon: Download, label: 'Downloads' },
    ],
  },
  {
    label: 'Discover',
    items: [
      { to: '/discover', icon: Compass, label: 'Discover' },
      { to: '/search', icon: Search, label: 'Search', kbd: 'Ctrl K' },
    ],
  },
  {
    label: 'Account',
    items: [
      { to: '/profile', icon: User, label: 'Profile' },
      { to: '/stats', icon: Activity, label: 'Stats' },
      { to: '/settings', icon: Settings, label: 'Settings' },
    ],
  },
]

interface Props {
  auth: AuthState
  onLogout: () => void
}

export default function AppShell({ auth, onLogout }: Props) {
  const pinned = useSidebarStore(s => s.pinned)
  const togglePinned = useSidebarStore(s => s.togglePinned)
  const pinnedWidth = useSidebarStore(s => s.pinnedWidth)
  const setPinnedWidth = useSidebarStore(s => s.setPinnedWidth)
  const resetPinnedWidth = useSidebarStore(s => s.resetPinnedWidth)
  const [hovered, setHovered] = useState(false)
  const [resizing, setResizing] = useState(false)
  const [nowPlayingOpen, setNowPlayingOpen] = useState(false)

  const expanded = pinned || hovered
  // When pinned the user controls the width; hover-expanded uses the default
  const targetWidth = !expanded
    ? SIDEBAR_COLLAPSED_W
    : pinned
      ? pinnedWidth
      : SIDEBAR_DEFAULT_W

  function startResize(e: React.PointerEvent<HTMLDivElement>) {
    if (!pinned) return
    e.preventDefault()
    setResizing(true)
    const startX = e.clientX
    const startW = pinnedWidth

    document.body.style.cursor = 'col-resize'
    document.body.style.userSelect = 'none'

    function onMove(ev: PointerEvent) {
      const next = Math.max(SIDEBAR_MIN_W, Math.min(SIDEBAR_MAX_W, startW + (ev.clientX - startX)))
      setPinnedWidth(next)
    }
    function onUp() {
      setResizing(false)
      document.body.style.cursor = ''
      document.body.style.userSelect = ''
      document.removeEventListener('pointermove', onMove)
      document.removeEventListener('pointerup', onUp)
    }
    document.addEventListener('pointermove', onMove)
    document.addEventListener('pointerup', onUp)
  }

  function resetWidth() {
    if (!pinned) return
    resetPinnedWidth()
  }

  return (
    <Tooltip.Provider delayDuration={400} skipDelayDuration={150}>
      <div className="h-full w-full flex flex-col bg-void text-text-1">
        {/* Single chrome bar at the top: brand + pin + back/title + search +
            window controls. Replaces the old sidebar brand row + TopBar +
            Tauri-only Titlebar. */}
        <AppHeader pinned={pinned} onTogglePin={togglePinned} />

        <div className="flex-1 flex overflow-hidden min-h-0">
          <motion.aside
            className="app-sidebar h-full glass border-r border-border flex flex-col shrink-0 relative z-sidebar"
            initial={false}
            animate={{ width: targetWidth }}
            transition={resizing ? { duration: 0 } : { duration: 0.32, ease: [0.16, 1, 0.3, 1] }}
            onMouseEnter={() => setHovered(true)}
            onMouseLeave={() => setHovered(false)}
          >
            <LayoutGroup id="sidebar-nav">
              <nav className="flex-1 py-3 flex flex-col gap-3 overflow-y-auto hide-scrollbar">
                {NAV_SECTIONS.map(section => (
                  <Section key={section.label} section={section} expanded={expanded} />
                ))}

                <div className="mt-auto px-3">
                  <SidebarItem
                    expanded={expanded}
                    item={{ to: '#logout', icon: LogOut, label: 'Sign out' }}
                    asButton
                    onClick={onLogout}
                  />
                </div>
              </nav>
            </LayoutGroup>

            <UserCard auth={auth} expanded={expanded} />

            {pinned && (
              <div
                role="separator"
                aria-orientation="vertical"
                aria-label="Resize sidebar"
                onPointerDown={startResize}
                onDoubleClick={resetWidth}
                className={`group/resize absolute top-0 right-0 h-full w-2 -mr-1 cursor-col-resize z-10 ${
                  resizing ? 'pointer-events-auto' : ''
                }`}
                title="Drag to resize · Double-click to reset"
              >
                <span
                  className={`absolute right-1 top-0 bottom-0 w-px transition-all duration-150 ${
                    resizing
                      ? 'bg-accent shadow-[0_0_8px_rgba(245,182,66,0.6)]'
                      : 'bg-transparent group-hover/resize:bg-accent/60'
                  }`}
                />
              </div>
            )}
          </motion.aside>

          {/* Main pane */}
          <div className="flex-1 flex flex-col min-w-0 relative">
            <OfflineBanner />
            <main className="flex-1 overflow-y-auto content-scroll relative">
              <Suspense fallback={<RouteFallback />}>
                <Outlet />
              </Suspense>
            </main>
            <MiniPlayer onExpand={() => setNowPlayingOpen(true)} />
          </div>
        </div>

        <NowPlaying isOpen={nowPlayingOpen} onClose={() => setNowPlayingOpen(false)} />
        <QuickLookModal />
        <YoutubeViewerModal />
        <RequestModalMount />
        <ToastHost />
      </div>
    </Tooltip.Provider>
  )
}

function RequestModalMount() {
  const open = useRequestModal(s => s.open)
  const tmdbId = useRequestModal(s => s.tmdbId)
  const kind = useRequestModal(s => s.kind)
  const tmdbData = useRequestModal(s => s.tmdbData)
  const close = useRequestModal(s => s.close)
  if (!tmdbId) return null
  return (
    <RequestModal
      open={open}
      onClose={close}
      tmdbId={tmdbId}
      kind={kind}
      tmdbData={tmdbData}
    />
  )
}

function RouteFallback() {
  return (
    <div className="h-full grid place-items-center">
      <div className="flex items-center gap-2 text-text-3 text-[12.5px] font-medium">
        <span className="w-1 h-1 rounded-full bg-accent animate-pulse" />
        Loading
      </div>
    </div>
  )
}

/* ──────────────────────────────────────────────────────────── */
/*  Section + Item                                              */
/* ──────────────────────────────────────────────────────────── */

function Section({ section, expanded }: { section: NavSection; expanded: boolean }) {
  return (
    <div className="px-3">
      <AnimatePresence>
        {expanded && (
          <motion.p
            initial={{ opacity: 0, y: -2 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -2 }}
            transition={{ duration: 0.18 }}
            className="text-[10px] uppercase tracking-[0.18em] font-semibold text-text-4 px-2.5 mb-1.5 leading-none"
          >
            {section.label}
          </motion.p>
        )}
      </AnimatePresence>
      <div className="flex flex-col gap-0.5">
        {section.items.map(item => (
          <SidebarItem key={item.to} item={item} expanded={expanded} />
        ))}
      </div>
    </div>
  )
}

interface SidebarItemProps {
  item: NavItem
  expanded: boolean
  asButton?: boolean
  onClick?: () => void
}

function SidebarItem({ item, expanded, asButton = false, onClick }: SidebarItemProps) {
  const inner = (isActive: boolean) => (
    <>
      {/* Left active rail */}
      {isActive && (
        <motion.span
          layoutId="sidebar-active-rail"
          className="absolute left-0 top-1.5 bottom-1.5 w-[3px] rounded-r-full bg-accent shadow-[0_0_8px_rgba(245,182,66,0.6)]"
          transition={{ type: 'spring', stiffness: 380, damping: 32 }}
        />
      )}

      <span
        className={`relative w-9 h-10 grid place-items-center shrink-0 transition-colors duration-150 ${
          isActive ? 'text-accent' : 'text-text-3 group-hover:text-text-1'
        }`}
      >
        <item.icon size={17} stroke={isActive ? 2.2 : 1.75} />
      </span>

      <AnimatePresence>
        {expanded && (
          <motion.span
            initial={{ opacity: 0, x: -4 }}
            animate={{ opacity: 1, x: 0 }}
            exit={{ opacity: 0, x: -4 }}
            transition={{ duration: 0.18 }}
            className={`relative flex-1 text-[13px] font-medium tracking-tight whitespace-nowrap ${
              isActive ? 'text-accent' : 'text-text-2 group-hover:text-text-1'
            }`}
          >
            {item.label}
          </motion.span>
        )}
      </AnimatePresence>

      <AnimatePresence>
        {expanded && item.kbd && (
          <motion.kbd
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.18 }}
            className="relative shrink-0 mr-2.5 px-1.5 h-5 inline-flex items-center rounded text-[10px] font-mono text-text-4 bg-void/60 border border-border"
          >
            {item.kbd}
          </motion.kbd>
        )}
      </AnimatePresence>
    </>
  )

  const baseCls =
    'group relative flex items-center h-10 rounded-lg w-full focus-ring overflow-hidden'

  const node = asButton ? (
    <button
      type="button"
      onClick={onClick}
      className={`${baseCls} text-text-3 hover:text-text-1`}
    >
      {inner(false)}
    </button>
  ) : (
    <NavLink
      to={item.to}
      end={item.to === '/'}
      className={({ isActive }) =>
        `${baseCls} ${isActive ? 'bg-glass-light' : 'hover:bg-glass-light'}`
      }
    >
      {({ isActive }) => inner(isActive)}
    </NavLink>
  )

  // Wrap in tooltip - only renders when collapsed
  if (expanded) return node
  return (
    <Tooltip.Root>
      <Tooltip.Trigger asChild>{node}</Tooltip.Trigger>
      <Tooltip.Portal>
        <Tooltip.Content
          side="right"
          sideOffset={10}
          className="z-toast inline-flex items-center gap-2 px-2.5 h-7 rounded-md bg-glass-strong backdrop-blur-xl border border-border-hover text-[12px] text-text-1 font-medium shadow-lg select-none"
        >
          {item.label}
          {item.kbd && (
            <kbd className="inline-flex items-center px-1.5 h-4 rounded text-[10px] font-mono text-text-4 bg-void/60 border border-border">
              {item.kbd}
            </kbd>
          )}
        </Tooltip.Content>
      </Tooltip.Portal>
    </Tooltip.Root>
  )
}

/* ──────────────────────────────────────────────────────────── */
/*  User card                                                   */
/* ──────────────────────────────────────────────────────────── */

function UserCard({ auth, expanded }: { auth: AuthState; expanded: boolean }) {
  const initial = (auth.userName || 'U')[0].toUpperCase()
  const serverHost = (() => {
    try {
      return auth.serverUrl ? new URL(auth.serverUrl).host : ''
    } catch { return '' }
  })()

  return (
    <div className="px-3 py-3 border-t border-border shrink-0">
      <div className="group flex items-center h-11 rounded-lg px-1.5 hover:bg-glass-light transition-colors cursor-default min-w-0">
        <div className="relative shrink-0">
          <div className="w-8 h-8 rounded-full bg-gradient-to-br from-accent/30 via-higher to-elevated grid place-items-center text-text-1 text-[12px] font-bold ring-1 ring-border font-display">
            {initial}
          </div>
          <span className="absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full bg-success ring-2 ring-surface" aria-label="Online" />
        </div>
        <AnimatePresence>
          {expanded && (
            <motion.div
              initial={{ opacity: 0, x: -4 }}
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: -4 }}
              transition={{ duration: 0.18 }}
              className="ml-2.5 min-w-0 flex-1 leading-tight"
            >
              <p className="text-[12.5px] text-text-1 font-semibold truncate tracking-tight">
                {auth.userName || 'User'}
              </p>
              {serverHost && (
                <p className="text-[10px] text-text-4 truncate tabular-nums">{serverHost}</p>
              )}
            </motion.div>
          )}
        </AnimatePresence>
      </div>
    </div>
  )
}
