import { useState, useEffect, useCallback } from 'react'
import { Sun, Moon, Palette } from 'lucide-react'
import {
  toggleTheme,
  getCurrentTheme,
  getThemeLabel,
  getNextTheme,
  type Theme,
  type ResolvedTheme,
} from '../../ui/index'

export interface ThemeIconProps {
  theme: string
  className?: string
  size?: number
}

/**
 * Renders the appropriate icon for a given theme string.
 *
 * - `"light"` renders a Sun icon
 * - `"monokai"` or `"glass"` renders a Palette icon
 * - Everything else (including `"dark"`) renders a Moon icon
 */
export function ThemeIcon({ theme, className, size }: ThemeIconProps) {
  const props: Record<string, string | number> = {}
  if (className !== undefined) {
    props.className = className
  }
  if (size !== undefined) {
    props.size = size
  }

  switch (theme) {
    case 'light':
      return <Sun {...props} />
    case 'monokai':
    case 'glass':
      return <Palette {...props} />
    default:
      return <Moon {...props} />
  }
}

export interface ThemeToggleButtonProps {
  className?: string
}

/**
 * A button that cycles through available themes on click.
 *
 * Displays an icon matching the current theme and a title/tooltip
 * describing the current theme and prompting to switch.
 */
export function ThemeToggleButton({ className }: ThemeToggleButtonProps) {
  const { theme, themeLabel, toggle } = useThemeState()

  return (
    <button
      type="button"
      onClick={toggle}
      title={`${themeLabel} — click to switch`}
      className={className}
    >
      <ThemeIcon theme={theme} />
    </button>
  )
}

export interface UseThemeStateResult {
  /** The current resolved theme applied to the document */
  theme: ResolvedTheme
  /** Human-readable label for the current theme */
  themeLabel: string
  /** The theme that will be applied on the next toggle */
  nextTheme: Theme
  /** Human-readable label for the next theme */
  nextThemeLabel: string
  /** Cycle to the next theme */
  toggle: () => void
}

/**
 * React hook that wraps the ui module's theme state.
 *
 * Listens for DOM attribute mutations on `data-theme` so the
 * component re-renders whenever the theme changes, whether the
 * change was triggered by this hook or by external code.
 */
export function useThemeState(): UseThemeStateResult {
  const [theme, setTheme] = useState<ResolvedTheme>(() => getCurrentTheme() as ResolvedTheme)

  useEffect(() => {
    const observer = new MutationObserver(() => {
      const current = getCurrentTheme() as ResolvedTheme
      setTheme(prev => (prev === current ? prev : current))
    })

    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['data-theme'],
    })

    return () => {
      observer.disconnect()
    }
  }, [])

  const toggle = useCallback(() => {
    const next = toggleTheme()
    setTheme(next as ResolvedTheme)
  }, [])

  const nextTheme = getNextTheme(theme)

  return {
    theme,
    themeLabel: getThemeLabel(theme),
    nextTheme,
    nextThemeLabel: getThemeLabel(nextTheme),
    toggle,
  }
}
