import {
  Caption1,
  CounterBadge,
  makeStyles,
  mergeClasses,
  tokens,
  shorthands
} from '@fluentui/react-components'
import {
  ArrowDownloadFilled,
  ArrowDownloadRegular,
  HistoryRegular,
  LibraryRegular,
  WindowConsoleRegular,
  SettingsRegular,
  WeatherMoonRegular,
  WeatherSunnyRegular,
  DesktopRegular,
  PanelLeftContractRegular,
  PanelLeftExpandRegular
} from '@fluentui/react-icons'
import type { ThemeMode } from '@shared/ipc'
import { Hint } from './Hint'
import { SegmentedControl } from './ui/SegmentedControl'
import { IconButton } from './ui/IconButton'
import { useFocusStyles } from './ui/focusRing'
import { useTextStyles } from './ui/text'
import { MOTION, ICON } from './ui/tokens'

export type TabValue = 'downloads' | 'library' | 'history' | 'terminal' | 'settings'

const useStyles = makeStyles({
  root: {
    width: '212px',
    flexShrink: 0,
    display: 'flex',
    flexDirection: 'column',
    gap: '4px',
    padding: '16px 12px',
    backgroundColor: tokens.colorNeutralBackground1,
    borderRight: `1px solid ${tokens.colorNeutralStroke2}`,
    // The app's one motion timing, gated globally on prefers-reduced-motion (UI26).
    transition: `width ${MOTION.duration} ${MOTION.curve}`
  },
  rootCollapsed: {
    width: '60px',
    alignItems: 'center'
  },
  topBar: {
    display: 'flex',
    justifyContent: 'flex-end',
    paddingBottom: '2px'
  },
  topBarCollapsed: {
    justifyContent: 'center'
  },
  brand: {
    display: 'flex',
    alignItems: 'center',
    gap: '11px',
    padding: '0 10px 14px'
  },
  brandCollapsed: {
    padding: '0 0 12px',
    justifyContent: 'center'
  },
  mark: {
    width: '36px',
    height: '36px',
    flexShrink: 0,
    borderRadius: tokens.borderRadiusLarge,
    backgroundColor: tokens.colorBrandBackground,
    color: tokens.colorNeutralForegroundOnBrand,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    // Brand tile glyph, snapped to the nearest ICON tier (UI11 — no literal px).
    fontSize: `${ICON.control}px`
  },
  brandText: {
    display: 'flex',
    flexDirection: 'column',
    minWidth: 0
  },
  brandName: {
    fontSize: tokens.fontSizeBase400,
    fontWeight: tokens.fontWeightSemibold,
    lineHeight: tokens.lineHeightBase400,
    color: tokens.colorNeutralForeground1
  },
  nav: {
    display: 'flex',
    flexDirection: 'column',
    gap: '3px',
    alignSelf: 'stretch'
  },
  navItem: {
    // relative so the collapsed count badge can pin to the icon's corner.
    position: 'relative',
    display: 'flex',
    alignItems: 'center',
    gap: '11px',
    width: '100%',
    padding: '9px 12px',
    ...shorthands.borderRadius(tokens.borderRadiusMedium),
    border: 'none',
    backgroundColor: 'transparent',
    color: tokens.colorNeutralForeground2,
    fontSize: tokens.fontSizeBase300,
    fontFamily: tokens.fontFamilyBase,
    textAlign: 'left',
    cursor: 'pointer',
    ':hover': {
      backgroundColor: tokens.colorNeutralBackground1Hover
    }
  },
  // Expanded: the active-download count sits at the far right of the nav row.
  navBadge: {
    marginLeft: 'auto'
  },
  // Collapsed: pin the count to the top-right corner of the centered icon.
  navBadgeCollapsed: {
    position: 'absolute',
    top: '4px',
    right: '8px'
  },
  navItemCollapsed: {
    justifyContent: 'center',
    padding: '9px 0'
  },
  navItemActive: {
    backgroundColor: tokens.colorBrandBackground2,
    color: tokens.colorBrandForeground2,
    fontWeight: tokens.fontWeightSemibold,
    // The active-nav rail shows in BOTH sidebar states (UI21) — collapsed used to
    // rely on tint alone. It hugs the row's left edge, clear of the collapsed
    // count badge pinned at the icon's top-right.
    boxShadow: `inset 3px 0 0 0 ${tokens.colorCompoundBrandStroke}`,
    ':hover': {
      backgroundColor: tokens.colorBrandBackground2
    }
  },
  navIcon: {
    fontSize: `${ICON.control}px`,
    flexShrink: 0,
    display: 'flex'
  },
  spacer: {
    flexGrow: 1
  }
})

const NAV: { value: TabValue; label: string; icon: React.JSX.Element }[] = [
  { value: 'downloads', label: 'Downloads', icon: <ArrowDownloadRegular /> },
  { value: 'library', label: 'Library', icon: <LibraryRegular /> },
  { value: 'history', label: 'History', icon: <HistoryRegular /> },
  { value: 'terminal', label: 'Terminal', icon: <WindowConsoleRegular /> },
  { value: 'settings', label: 'Settings', icon: <SettingsRegular /> }
]

const THEMES: { value: ThemeMode; label: string; icon: React.JSX.Element }[] = [
  { value: 'light', label: 'Light', icon: <WeatherSunnyRegular /> },
  { value: 'dark', label: 'Dark', icon: <WeatherMoonRegular /> },
  { value: 'system', label: 'Auto', icon: <DesktopRegular /> }
]

interface SidebarProps {
  tab: TabValue
  onTabChange: (t: TabValue) => void
  /** the current theme preference: explicit light/dark, or 'system' to follow the OS */
  theme: ThemeMode
  /** whether the resolved theme is currently dark (drives the collapsed toggle icon) */
  isDark: boolean
  onSetTheme: (mode: ThemeMode) => void
  /** AeroFetch version string, e.g. '0.3.2' ('' until loaded) */
  version: string
  collapsed: boolean
  onToggleCollapsed: () => void
  /** Show the Terminal nav item (only when custom commands are enabled) */
  showTerminal: boolean
  /** Active (downloading + queued) count, badged on the Downloads nav item (UX9). */
  downloadCount: number
}

export function Sidebar({
  tab,
  onTabChange,
  theme,
  isDark,
  onSetTheme,
  version,
  collapsed,
  onToggleCollapsed,
  showTerminal,
  downloadCount
}: SidebarProps): React.JSX.Element {
  const styles = useStyles()
  const focus = useFocusStyles()
  const text = useTextStyles()

  // Collapsed view shows one button that cycles Light → Dark → Auto.
  const order: ThemeMode[] = ['light', 'dark', 'system']
  function cycleTheme(): void {
    const next = order[(order.indexOf(theme) + 1) % order.length]
    if (next) onSetTheme(next)
  }
  const themeIcon =
    theme === 'system' ? (
      <DesktopRegular fontSize={ICON.control} />
    ) : isDark ? (
      <WeatherMoonRegular fontSize={ICON.control} />
    ) : (
      <WeatherSunnyRegular fontSize={ICON.control} />
    )
  const themeLabel = theme === 'system' ? 'Auto (system)' : isDark ? 'Dark' : 'Light'

  return (
    <nav className={mergeClasses(styles.root, collapsed && styles.rootCollapsed)}>
      <div className={mergeClasses(styles.topBar, collapsed && styles.topBarCollapsed)}>
        <Hint label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'} placement="right">
          <IconButton
            icon={collapsed ? <PanelLeftExpandRegular /> : <PanelLeftContractRegular />}
            onClick={onToggleCollapsed}
            aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
            aria-pressed={collapsed}
          />
        </Hint>
      </div>

      <div className={mergeClasses(styles.brand, collapsed && styles.brandCollapsed)}>
        <div className={styles.mark}>
          <ArrowDownloadFilled />
        </div>
        {!collapsed && (
          <div className={styles.brandText}>
            <span className={styles.brandName}>AeroFetch</span>
            {/* Stable tagline so the caption never flips from text to a version
                string once it loads (L66); the version shows on hover and in
                Settings → About. */}
            <Caption1 className={text.muted} title={version ? `Version ${version}` : undefined}>
              Video downloader
            </Caption1>
          </div>
        )}
      </div>

      <div className={styles.nav}>
        {NAV.filter((n) => n.value !== 'terminal' || showTerminal).map((n) => {
          const active = tab === n.value
          const btn = (
            <button
              key={n.value}
              type="button"
              className={mergeClasses(
                styles.navItem,
                collapsed && styles.navItemCollapsed,
                active && styles.navItemActive,
                focus.focusRing
              )}
              onClick={() => onTabChange(n.value)}
              aria-current={active ? 'page' : undefined}
              aria-label={
                n.value === 'downloads' && downloadCount > 0
                  ? `${n.label}, ${downloadCount} active`
                  : n.label
              }
            >
              <span className={styles.navIcon}>{n.icon}</span>
              {!collapsed && n.label}
              {n.value === 'downloads' && downloadCount > 0 && (
                <CounterBadge
                  className={collapsed ? styles.navBadgeCollapsed : styles.navBadge}
                  count={downloadCount}
                  size="small"
                  color="brand"
                  aria-hidden
                />
              )}
            </button>
          )
          return collapsed ? (
            <Hint key={n.value} label={n.label} placement="right">
              {btn}
            </Hint>
          ) : (
            btn
          )
        })}
      </div>

      <div className={styles.spacer} />

      {collapsed ? (
        <Hint label={`Theme: ${themeLabel}`} placement="right">
          <IconButton
            icon={themeIcon}
            onClick={cycleTheme}
            aria-label={`Change theme (currently ${themeLabel})`}
          />
        </Hint>
      ) : (
        <SegmentedControl<ThemeMode>
          fitted
          value={theme}
          options={THEMES}
          onChange={onSetTheme}
          ariaLabel="Theme"
        />
      )}
    </nav>
  )
}
