import { useEffect, useLayoutEffect, useMemo, useState, type ComponentType } from 'react'
import { motion } from 'framer-motion'
import {
  Server,
  Play as PlayIcon,
  Key,
  Info,
  Globe,
  Lock,
  Palette,
  Volume2,
  Database,
  Home,
  ListDetails,
  Tv,
  User,
  Search,
  Hash,
  Activity,
  X,
} from '../lib/icons'
import { getStoredAuth } from '../api/jellyfin'
import { usePreferencesStore } from '../stores/preferences-store'
import { SettingsSearchContext, type SettingsSearchValue } from './settings/_ui'
import { ServerSection } from './settings/sections/Server'
import { ServersSection } from './settings/sections/Servers'
import { ServerDashboardSection } from './settings/sections/ServerDashboard'
import { PlaybackSection } from './settings/sections/Playback'
import { AudioSection } from './settings/sections/Audio'
import { DisplaySection } from './settings/sections/Display'
import { HomePageSection } from './settings/sections/Home'
import { DetailPageSection } from './settings/sections/Detail'
import { EpisodesSection } from './settings/sections/Episodes'
import { DiscoverySection } from './settings/sections/Discovery'
import { TmdbSection } from './settings/sections/Tmdb'
import { FanartSection } from './settings/sections/Fanart'
import { TraktSection } from './settings/sections/Trakt'
import { ArrSection } from './settings/sections/Arr'
import { PersonalSettingsSection } from './settings/sections/Personal'
import { PrivacySection } from './settings/sections/Privacy'
import { AboutSection } from './settings/sections/About'
import { ShortcutsSection } from './settings/sections/Shortcuts'

/* ──────────────────────────────────────────────────────────── */
/*  Categories - drive the left-rail nav and section anchors   */
/* ──────────────────────────────────────────────────────────── */

interface Category {
  id: string
  icon: ComponentType<{ size?: number; stroke?: number; className?: string }>
  label: string
}

interface CategoryGroup {
  label: string
  items: Category[]
}

const CATEGORY_GROUPS: CategoryGroup[] = [
  {
    label: 'Account',
    items: [
      { id: 'server', icon: Server, label: 'Server' },
      { id: 'servers', icon: Server, label: 'All servers' },
      { id: 'server-dashboard', icon: Activity, label: 'Dashboard' },
    ],
  },
  {
    label: 'Playback',
    items: [
      { id: 'playback', icon: PlayIcon, label: 'Playback' },
      { id: 'audio', icon: Volume2, label: 'Audio & Subtitles' },
      { id: 'shortcuts', icon: Hash, label: 'Shortcuts' },
    ],
  },
  {
    label: 'Appearance',
    items: [
      { id: 'display', icon: Palette, label: 'Display' },
      { id: 'home-page', icon: Home, label: 'Home page' },
      { id: 'detail-page', icon: ListDetails, label: 'Detail page' },
      { id: 'episodes', icon: Tv, label: 'Episodes' },
    ],
  },
  {
    label: 'Discovery',
    items: [
      { id: 'discovery', icon: Globe, label: 'Region & content' },
      { id: 'tmdb', icon: Key, label: 'TMDB' },
      { id: 'fanart', icon: Palette, label: 'Fanart.tv' },
      { id: 'trakt', icon: Activity, label: 'Trakt.tv' },
    ],
  },
  {
    label: 'Requests',
    items: [
      { id: 'sonarr-radarr', icon: Database, label: 'Sonarr & Radarr' },
    ],
  },
  {
    label: 'Data',
    items: [
      { id: 'personal', icon: User, label: 'Your data' },
      { id: 'privacy', icon: Lock, label: 'Privacy' },
    ],
  },
  {
    label: 'About',
    items: [
      { id: 'about', icon: Info, label: 'About' },
    ],
  },
]

const CATEGORIES: Category[] = CATEGORY_GROUPS.flatMap(g => g.items)

export default function SettingsPage() {
  const prefs = usePreferencesStore()
  const auth = getStoredAuth()
  const serverHost = (() => {
    try { return auth?.serverUrl ? new URL(auth.serverUrl).host : '-' } catch { return '-' }
  })()

  const [active, setActive] = useState<string>('server')
  const [query, setQuery] = useState('')
  const trimmed = query.trim().toLowerCase()
  const search = useMemo<SettingsSearchValue>(
    () => ({
      query: trimmed,
      matches: (haystack: string) => {
        if (!trimmed) return true
        return haystack.toLowerCase().includes(trimmed)
      },
    }),
    [trimmed],
  )

  // Track the section closest to the top of the scroll viewport so the
  // nav highlights what the user is currently reading.
  useEffect(() => {
    const root = document.querySelector('main.content-scroll') as HTMLElement | null
    if (!root) return
    const obs = new IntersectionObserver(
      entries => {
        const visible = entries
          .filter(e => e.isIntersecting)
          .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)
        if (visible.length > 0) setActive(visible[0].target.id)
      },
      {
        root,
        rootMargin: '-15% 0px -65% 0px',
        threshold: 0,
      },
    )
    CATEGORIES.forEach(c => {
      const el = document.getElementById(c.id)
      if (el) obs.observe(el)
    })
    return () => obs.disconnect()
  }, [])

  function scrollTo(id: string) {
    const el = document.getElementById(id)
    el?.scrollIntoView({ behavior: 'smooth', block: 'start' })
  }

  return (
    <div className="px-7 pt-4 pb-16">
      <div className="mb-9 max-w-3xl">
        <div className="flex items-center gap-2 mb-1.5">
          <span className="w-1 h-3.5 rounded-full bg-accent" />
          <span className="text-[11px] font-semibold text-text-2 uppercase tracking-[0.14em]">Preferences</span>
        </div>
        <h1 className="text-3xl md:text-4xl font-bold font-display text-text-1 tracking-tight">Settings</h1>
        <p className="text-[13px] text-text-3 mt-1.5">Customize your Jellybloom experience</p>
      </div>

      <SettingsSearchContext.Provider value={search}>
        <div className="flex gap-10 items-start">
          <SectionNav
            active={active}
            onSelect={scrollTo}
            query={query}
            onQueryChange={setQuery}
          />

          <div className="flex-1 min-w-0 max-w-2xl space-y-12">
            <ServerSection serverHost={serverHost} userName={auth?.userName} />
            <ServersSection />
            <ServerDashboardSection />
            <PlaybackSection prefs={prefs} />
            <AudioSection prefs={prefs} />
            <ShortcutsSection />
            <DisplaySection prefs={prefs} />
            <HomePageSection prefs={prefs} />
            <DetailPageSection prefs={prefs} />
            <EpisodesSection prefs={prefs} />
            <DiscoverySection prefs={prefs} />
            <TmdbSection prefs={prefs} />
            <FanartSection prefs={prefs} />
            <TraktSection />
            <ArrSection />
            <PersonalSettingsSection />
            <PrivacySection />
            <AboutSection />
            <SettingsEmptyState query={trimmed} />
          </div>
        </div>
      </SettingsSearchContext.Provider>
    </div>
  )
}

/**
 * "No results" message shown when the current search query hides every
 * row on the page. Uses an effect to count visible rows via DOM rather
 * than threading state through every row.
 */
function SettingsEmptyState({ query }: { query: string }) {
  const [empty, setEmpty] = useState(false)
  useLayoutEffect(() => {
    if (!query) {
      setEmpty(false)
      return
    }
    const visible = document.querySelectorAll('[data-settings-row]').length
    setEmpty(visible === 0)
  }, [query])
  if (!query || !empty) return null
  return (
    <div className="rounded-xl bg-elevated/30 border border-border p-8 text-center">
      <p className="text-[13px] text-text-2 font-medium mb-1.5">No settings match "{query}"</p>
      <p className="text-[11.5px] text-text-4">Try a different keyword, or clear the search to browse everything.</p>
    </div>
  )
}

function SectionNav({
  active,
  onSelect,
  query,
  onQueryChange,
}: {
  active: string
  onSelect: (id: string) => void
  query: string
  onQueryChange: (next: string) => void
}) {
  return (
    <nav className="hidden md:flex flex-col gap-4 w-[224px] shrink-0 sticky top-4">
      <div className="relative">
        <Search
          size={13}
          stroke={2}
          className="absolute left-3 top-1/2 -translate-y-1/2 text-text-4 pointer-events-none"
        />
        <input
          type="search"
          value={query}
          onChange={e => onQueryChange(e.target.value)}
          placeholder="Search settings..."
          className="w-full h-9 pl-9 pr-9 rounded-md bg-elevated/40 ring-1 ring-border focus:ring-accent/50 outline-none text-[12.5px] tracking-tight text-text-1 placeholder:text-text-4 transition"
        />
        {query && (
          <button
            type="button"
            onClick={() => onQueryChange('')}
            aria-label="Clear search"
            className="absolute right-2 top-1/2 -translate-y-1/2 w-5 h-5 grid place-items-center rounded-full text-text-4 hover:text-text-1 hover:bg-elevated transition"
          >
            <X size={11} stroke={2} />
          </button>
        )}
      </div>

      <ul className="flex flex-col gap-4">
        {CATEGORY_GROUPS.map(group => (
          <li key={group.label}>
            <p className="text-[10px] uppercase tracking-[0.18em] font-semibold text-text-4 mb-1.5 ml-3">
              {group.label}
            </p>
            <ul className="flex flex-col gap-0.5">
              {group.items.map(c => {
                const isActive = active === c.id
                return (
                  <li key={c.id}>
                    <button
                      type="button"
                      onClick={() => onSelect(c.id)}
                      className={`relative w-full flex items-center gap-2.5 h-9 pl-3 pr-3 rounded-md transition-colors duration-150 focus-ring ${
                        isActive ? 'bg-glass-light text-accent' : 'text-text-3 hover:text-text-1 hover:bg-glass-light/60'
                      }`}
                    >
                      {isActive && (
                        <motion.span
                          layoutId="settings-active-rail"
                          className="absolute left-0 top-1.5 bottom-1.5 w-[2.5px] rounded-r-full bg-accent shadow-[0_0_6px_rgba(245,182,66,0.55)]"
                          transition={{ type: 'spring', stiffness: 380, damping: 32 }}
                        />
                      )}
                      <c.icon size={14} stroke={isActive ? 2.2 : 1.75} className="shrink-0" />
                      <span className="text-[12.5px] font-medium tracking-tight truncate">{c.label}</span>
                    </button>
                  </li>
                )
              })}
            </ul>
          </li>
        ))}
      </ul>
    </nav>
  )
}
