import { useCallback, useEffect, useMemo, useState, type ReactNode } from 'react'
import { THEME_STORAGE_KEY, ThemeContext, type Theme } from './theme-context'

function resolve(theme: Theme): 'light' | 'dark' {
  if (theme === 'system') {
    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
  }
  return theme
}

function applyTheme(theme: Theme) {
  const root = document.documentElement
  root.classList.toggle('dark', resolve(theme) === 'dark')
}

export function ThemeProvider({ children }: Readonly<{ children: ReactNode }>) {
  const [theme, setTheme] = useState<Theme>(
    () => (localStorage.getItem(THEME_STORAGE_KEY) as Theme | null) ?? 'dark',
  )

  useEffect(() => {
    applyTheme(theme)
    if (theme !== 'system') return
    const media = window.matchMedia('(prefers-color-scheme: dark)')
    const onChange = () => applyTheme('system')
    media.addEventListener('change', onChange)
    return () => media.removeEventListener('change', onChange)
  }, [theme])

  // Выбор темы переживает перезагрузку, поэтому наружу отдаём не голый сеттер, а обёртку с записью.
  const changeTheme = useCallback((next: Theme) => {
    localStorage.setItem(THEME_STORAGE_KEY, next)
    setTheme(next)
  }, [])

  // Литерал в value пересоздавался бы на каждый рендер и перерисовывал всех потребителей темы.
  const value = useMemo(() => ({ theme, setTheme: changeTheme }), [theme, changeTheme])

  return <ThemeContext value={value}>{children}</ThemeContext>
}
