import { useEffect, useState } from 'react'
import { flushSync } from 'react-dom'
import type { AppTheme } from './theme'
import {
  applyTheme,
  getPreferredTheme,
  getThemeStorageKey,
  saveTheme,
} from './theme'
import { updateThemeWithTransition } from './themeTransition'

export function useTheme() {
  const [theme, setTheme] = useState<AppTheme>(() => getPreferredTheme())

  useEffect(() => {
    applyTheme(theme)
    saveTheme(theme)
  }, [theme])

  useEffect(() => {
    function handleStorage(event: StorageEvent) {
      if (event.key !== getThemeStorageKey()) return
      if (event.newValue !== 'light' && event.newValue !== 'dark') return

      setTheme(event.newValue)
    }

    window.addEventListener('storage', handleStorage)

    return () => {
      window.removeEventListener('storage', handleStorage)
    }
  }, [])

  function commitTheme(nextTheme: AppTheme) {
    applyTheme(nextTheme)
    saveTheme(nextTheme)
    flushSync(() => {
      setTheme(nextTheme)
    })
  }

  function toggleTheme(source?: Element | null) {
    const nextTheme = theme === 'dark' ? 'light' : 'dark'

    updateThemeWithTransition({
      source,
      theme: nextTheme,
      updateTheme: commitTheme,
    })
  }

  return {
    isDark: theme === 'dark',
    theme,
    setTheme,
    toggleTheme,
  }
}
