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

/**
 * Theme: 'light' (Earth) | 'dark' (Claude-warm) | 'system' (follow prefers-color-scheme).
 *
 * <p>Persist'ится в {@code localStorage[STORAGE_KEY]}. На mount читает saved
 * preference или fallback'ает к 'system'. Меняет {@code data-theme} attr на
 * {@code <html>} → CSS custom properties в styles.css переключают палитру.
 *
 * <p>{@code system} mode — если user ничего не выбрал, следим за prefers-color-scheme
 * media query. matchMedia listener обновляет attr реально-time при OS theme change.
 */

const STORAGE_KEY = 'ord-theme'

export type ThemePreference = 'light' | 'dark' | 'system'
export type ResolvedTheme = 'light' | 'dark'

type ThemeContextValue = {
  preference: ThemePreference
  resolved: ResolvedTheme
  setPreference: (next: ThemePreference) => void
}

const ThemeContext = createContext<ThemeContextValue | null>(null)

function readSystemPreference(): ResolvedTheme {
  if (typeof window === 'undefined') return 'light'
  return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}

function readSavedPreference(): ThemePreference {
  if (typeof window === 'undefined') return 'system'
  const raw = window.localStorage.getItem(STORAGE_KEY)
  if (raw === 'light' || raw === 'dark' || raw === 'system') return raw
  return 'system'
}

function applyToDom(theme: ResolvedTheme) {
  if (typeof document === 'undefined') return
  document.documentElement.setAttribute('data-theme', theme)
  // shadcn convention — добавляем .dark class тоже на случай third-party
  // компонентов которые ждут именно его. Custom variant в styles.css всё равно
  // их связывает, но эта мера держит совместимость на корню.
  if (theme === 'dark') {
    document.documentElement.classList.add('dark')
  } else {
    document.documentElement.classList.remove('dark')
  }
  // <meta name="color-scheme"> чтобы system browser UI (scrollbars, autofill)
  // был в гармонии с темой.
  let meta = document.querySelector<HTMLMetaElement>('meta[name="color-scheme"]')
  if (!meta) {
    meta = document.createElement('meta')
    meta.name = 'color-scheme'
    document.head.appendChild(meta)
  }
  meta.content = theme
}

export function ThemeProvider({ children }: { children: ReactNode }) {
  const [preference, setPreferenceState] = useState<ThemePreference>(() => readSavedPreference())
  const [systemResolved, setSystemResolved] = useState<ResolvedTheme>(() => readSystemPreference())

  // Слушаем OS theme change при mode='system'.
  useEffect(() => {
    if (typeof window === 'undefined') return
    const mq = window.matchMedia('(prefers-color-scheme: dark)')
    const handler = () => setSystemResolved(mq.matches ? 'dark' : 'light')
    mq.addEventListener('change', handler)
    return () => mq.removeEventListener('change', handler)
  }, [])

  const resolved: ResolvedTheme = preference === 'system' ? systemResolved : preference

  // Применяем к DOM каждый раз когда resolved меняется.
  useEffect(() => {
    applyToDom(resolved)
  }, [resolved])

  const setPreference = (next: ThemePreference) => {
    setPreferenceState(next)
    if (typeof window !== 'undefined') {
      window.localStorage.setItem(STORAGE_KEY, next)
    }
  }

  return (
    <ThemeContext.Provider value={{ preference, resolved, setPreference }}>
      {children}
    </ThemeContext.Provider>
  )
}

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