'use client'

import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'
import { getPresetTheme, DEFAULT_THEME_ID, ACCENT_STORAGE_KEY } from '@/lib/preset-themes'

type Theme = 'dark' | 'light' | 'system'

interface ThemeContextValue {
  theme: Theme
  resolvedTheme: 'dark' | 'light'
  setTheme: (theme: Theme) => void
  /** Active preset color theme id (e.g. 'forge', 'dracula'). */
  accentTheme: string
  /** Switch preset color theme; persists to localStorage. */
  setAccentTheme: (id: string) => void
}

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

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

/**
 * Hex → "r, g, b" string for multi-layer shadow border rings.
 * Returns null for non-hex colors (e.g. oklch), in which case the caller
 * leaves --foreground-rgb at its stylesheet default.
 */
function hexToRgb(hex: string): string | null {
  let r: number, g: number, b: number
  const m6 = hex.match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i)
  if (m6) {
    r = parseInt(m6[1]!, 16)
    g = parseInt(m6[2]!, 16)
    b = parseInt(m6[3]!, 16)
  } else {
    const m3 = hex.match(/^#?([a-f\d])([a-f\d])([a-f\d])$/i)
    if (!m3) return null
    r = parseInt(m3[1]! + m3[1]!, 16)
    g = parseInt(m3[2]! + m3[2]!, 16)
    b = parseInt(m3[3]! + m3[3]!, 16)
  }
  return `${r}, ${g}, ${b}`
}

/**
 * Inject a preset theme's 6 semantic colors (+ foreground-rgb) onto :root.
 * Surface ladder / ink / borders then re-derive automatically via color-mix
 * (see globals.css). Ported from craft-agents-oss themeToCSS.
 */
export function applyPresetTheme(themeId: string, isDark: boolean) {
  const theme = getPresetTheme(themeId)
  const c = isDark ? theme.dark : theme.light
  const root = document.documentElement
  root.style.setProperty('--bg-page', c.background)
  root.style.setProperty('--text-primary', c.foreground)
  root.style.setProperty('--accent-indigo', c.accent)
  root.style.setProperty('--accent-green', c.success)
  root.style.setProperty('--accent-amber', c.info)
  root.style.setProperty('--accent-coral', c.destructive)
  const rgb = hexToRgb(c.foreground)
  if (rgb) root.style.setProperty('--foreground-rgb', rgb)
}

export function ThemeProvider({ children }: { children: ReactNode }) {
  const [theme, setTheme] = useState<Theme>('dark')
  const [resolvedTheme, setResolvedTheme] = useState<'dark' | 'light'>('dark')
  const [accentTheme, setAccentThemeState] = useState<string>(DEFAULT_THEME_ID)

  // Load persisted preferences on mount
  useEffect(() => {
    const saved = localStorage.getItem('forge-theme')
    if (saved === 'dark' || saved === 'light' || saved === 'system') setTheme(saved)
    const savedAccent = localStorage.getItem(ACCENT_STORAGE_KEY)
    if (savedAccent) setAccentThemeState(savedAccent)
  }, [])

  // Resolve + apply light/dark (sets data-theme; drives resolvedTheme)
  useEffect(() => {
    localStorage.setItem('forge-theme', theme)

    if (theme === 'system') {
      const mq = window.matchMedia('(prefers-color-scheme: dark)')
      const resolved = mq.matches ? 'dark' : 'light'
      setResolvedTheme(resolved)
      document.documentElement.setAttribute('data-theme', resolved)

      const handler = (e: MediaQueryListEvent) => {
        const r = e.matches ? 'dark' : 'light'
        setResolvedTheme(r)
        document.documentElement.setAttribute('data-theme', r)
      }
      mq.addEventListener('change', handler)
      return () => mq.removeEventListener('change', handler)
    }

    const resolved = theme === 'light' ? 'light' : 'dark'
    setResolvedTheme(resolved)
    document.documentElement.setAttribute('data-theme', resolved)
  }, [theme])

  // Apply preset color theme whenever the theme id or light/dark changes.
  // (The inline script in layout.tsx applies the same before hydration to
  // avoid FOUC; this re-confirms it once React is ready.)
  useEffect(() => {
    applyPresetTheme(accentTheme, resolvedTheme === 'dark')
  }, [accentTheme, resolvedTheme])

  const setAccentTheme = (id: string) => {
    setAccentThemeState(id)
    localStorage.setItem(ACCENT_STORAGE_KEY, id)
  }

  return (
    <ThemeContext.Provider value={{ theme, resolvedTheme, setTheme, accentTheme, setAccentTheme }}>
      {children}
    </ThemeContext.Provider>
  )
}
