import { createContext, useCallback, useContext, useEffect, useState, type ReactNode } from 'react'

interface ThemeColors {
  [key: string]: string
}

interface Theme {
  name: string
  label: string
  colors: ThemeColors
}

interface ThemeContextValue {
  theme: Theme
  themeName: string
  setTheme: (name: string) => void
  themes: Record<string, Theme>
}

const STORAGE_KEY = 'frontend-library-theme'
const ThemeContext = createContext<ThemeContextValue | null>(null)

function applyThemeColors(theme: Theme) {
  const root = document.documentElement
  const cssVarMap: Record<string, string> = {
    background: '--background', foreground: '--foreground',
    card: '--card', cardForeground: '--card-foreground',
    popover: '--popover', popoverForeground: '--popover-foreground',
    primary: '--primary', primaryForeground: '--primary-foreground',
    secondary: '--secondary', secondaryForeground: '--secondary-foreground',
    muted: '--muted', mutedForeground: '--muted-foreground',
    accent: '--accent', accentForeground: '--accent-foreground',
    destructive: '--destructive', destructiveForeground: '--destructive-foreground',
    success: '--success', successForeground: '--success-foreground',
    warning: '--warning', warningForeground: '--warning-foreground',
    info: '--info', infoForeground: '--info-foreground',
    surface: '--surface', surfaceHover: '--surface-hover', overlay: '--overlay',
    border: '--border', input: '--input', ring: '--ring',
    chart1: '--chart-1', chart2: '--chart-2', chart3: '--chart-3', chart4: '--chart-4', chart5: '--chart-5',
    sidebar: '--sidebar', sidebarForeground: '--sidebar-foreground',
    sidebarPrimary: '--sidebar-primary', sidebarPrimaryForeground: '--sidebar-primary-foreground',
    sidebarAccent: '--sidebar-accent', sidebarAccentForeground: '--sidebar-accent-foreground',
    sidebarBorder: '--sidebar-border', sidebarRing: '--sidebar-ring',
  }
  Object.entries(cssVarMap).forEach(([key, cssVar]) => {
    if (theme.colors[key]) root.style.setProperty(cssVar, theme.colors[key])
  })
  if (theme.name === 'dark' || theme.name === 'midnight' || theme.name === 'sunset') {
    root.classList.add('dark')
  } else {
    root.classList.remove('dark')
  }
}

interface ThemeProviderProps {
  children: ReactNode
  themes: Record<string, Theme>
  defaultTheme?: string
}

export function ThemeProvider({ children, themes, defaultTheme: initialTheme }: ThemeProviderProps) {
  const [themeName, setThemeName] = useState<string>(() => {
    if (initialTheme) return initialTheme
    if (typeof window === 'undefined') return 'default'
    const stored = localStorage.getItem(STORAGE_KEY)
    if (stored && themes[stored]) return stored
    if (window.matchMedia('(prefers-color-scheme: dark)').matches) return 'dark'
    return 'default'
  })

  const theme = themes[themeName] ?? themes['default'] ?? Object.values(themes)[0]

  const setTheme = useCallback((name: string) => {
    if (themes[name]) {
      setThemeName(name)
      localStorage.setItem(STORAGE_KEY, name)
    }
  }, [themes])

  useEffect(() => { applyThemeColors(theme) }, [theme])

  useEffect(() => {
    const mq = window.matchMedia('(prefers-color-scheme: dark)')
    const handle = (e: MediaQueryListEvent) => {
      if (!localStorage.getItem(STORAGE_KEY)) setThemeName(e.matches ? 'dark' : 'default')
    }
    mq.addEventListener('change', handle)
    return () => mq.removeEventListener('change', handle)
  }, [])

  return <ThemeContext.Provider value={{ theme, themeName, setTheme, themes }}>{children}</ThemeContext.Provider>
}

export function useTheme() {
  const ctx = useContext(ThemeContext)
  if (!ctx) throw new Error('useTheme must be used within a ThemeProvider')
  return ctx
}

export { ThemeContext }
export type { ThemeContextValue, ThemeProviderProps, Theme, ThemeColors }
