import { createContext, useContext, useState, useCallback, useEffect, useMemo, useRef } from 'react'
import en from './en'
import fr from './fr'
import { getLayout, getLayoutList } from './keyboards'
import api from '../api/client'

const translations = { en, fr }

const STORAGE_KEY_LANG = 'muyue-language'
const STORAGE_KEY_KBD = 'muyue-keyboard'

const I18nContext = createContext(null)

function resolveLocale(layout) {
  const l = getLayout(layout)
  return l.locale
}

export function I18nProvider({ children }) {
  const [language, setLanguageState] = useState(() => localStorage.getItem(STORAGE_KEY_LANG) || 'fr')
  const [keyboard, setKeyboardState] = useState(() => localStorage.getItem(STORAGE_KEY_KBD) || 'azerty')
  const [loaded, setLoaded] = useState(false)
  const pendingSave = useRef(null)

  useEffect(() => {
    api.getConfig()
      .then(d => {
        const prefs = d.profile?.preferences
        if (prefs?.language) setLanguageState(prefs.language)
        if (prefs?.keyboard_layout) setKeyboardState(prefs.keyboard_layout)
      })
      .catch(() => {})
      .finally(() => setLoaded(true))
  }, [])

  useEffect(() => {
    if (!loaded) return
    if (pendingSave.current) clearTimeout(pendingSave.current)
    pendingSave.current = setTimeout(() => {
      api.savePreferences({ language, keyboard_layout: keyboard }).catch(() => {})
    }, 500)
    return () => { if (pendingSave.current) clearTimeout(pendingSave.current) }
  }, [language, keyboard, loaded])

  const setLanguage = useCallback((lang) => {
    setLanguageState(lang)
    localStorage.setItem(STORAGE_KEY_LANG, lang)
  }, [])

  const setKeyboard = useCallback((kbd) => {
    setKeyboardState(kbd)
    localStorage.setItem(STORAGE_KEY_KBD, kbd)
  }, [])

  const layout = useMemo(() => getLayout(keyboard), [keyboard])

  const t = useCallback((key, params) => {
    const dict = translations[language] || translations.fr
    const keys = key.split('.')
    let value = dict
    for (const k of keys) {
      if (value == null) return key
      value = value[k]
    }
    if (typeof value !== 'string') return key
    if (params) {
      return Object.entries(params).reduce((str, [k, v]) => str.replace(`{${k}}`, v), value)
    }
    return value
  }, [language])

  const clockLocale = useMemo(() => resolveLocale(keyboard), [keyboard])

  const contextValue = useMemo(() => ({
    language,
    keyboard,
    layout,
    setLanguage,
    setKeyboard,
    t,
    clockLocale,
    layouts: getLayoutList(),
  }), [language, keyboard, layout, t, clockLocale])

  return (
    <I18nContext.Provider value={contextValue}>
      {children}
    </I18nContext.Provider>
  )
}

export function useI18n() {
  const ctx = useContext(I18nContext)
  if (!ctx) throw new Error('useI18n must be used within I18nProvider')
  return ctx
}

export const LANGUAGES = [
  { id: 'fr', name: 'Fran\u00e7ais' },
  { id: 'en', name: 'English' },
]
