import React, { createContext, useContext, useMemo } from 'react'
import type { I18nString } from '@pikku/react'
import type { SupportedLocale } from '@/config'
import { mKey } from '@/i18n/messages'
import { setRouteLocale, supportedLocales, defaultLocale } from '@/i18n/config'

export type GetNamespaced = (
  key: string,
  variables?: Record<string, any>
) => I18nString

export interface I18nContextType {
  locale: SupportedLocale
  get: GetNamespaced
  getEnumOptions: (
    e: Record<string, string>,
    enumName: string
  ) => { value: string; label: I18nString }[]
}

// Resolve any dotted i18n key through Paraglide (mKey snake_cases it and calls
// the compiled message). Replaces the old i18next `t`.
const get: GetNamespaced = (key, variables) => mKey(key, variables)

const getEnumOptions = (enumObject: Record<string, string>, enumName: string) =>
  Object.values(enumObject).map((value) => ({
    value,
    label: mKey(`enums.${enumName}.${value}`.toLowerCase()),
  }))

export const I18nContext = createContext<I18nContextType>({
  locale: defaultLocale as SupportedLocale,
  get,
  getEnumOptions,
})

// useI18n() returns a callable `t` (Paraglide-backed) augmented with the same
// helpers components used under i18next: `t('key')`, `t.getEnumOptions(...)`,
// `t.locale`.
export const useI18n = () => {
  const ctx = useContext(I18nContext)
  const t = (key: string, variables?: Record<string, any>): I18nString =>
    mKey(key, variables)
  return Object.assign(t, {
    get: ctx.get,
    getEnumOptions: ctx.getEnumOptions,
    locale: ctx.locale,
  })
}

interface I18nProviderProps {
  children: React.ReactNode
  lang?: string
}

const normalize = (lang: string): SupportedLocale => {
  const short = lang.slice(0, 2).toLowerCase()
  return (
    supportedLocales.includes(short as (typeof supportedLocales)[number])
      ? short
      : defaultLocale
  ) as SupportedLocale
}

export function I18nProvider({ children, lang = 'en' }: I18nProviderProps) {
  const locale = normalize(lang)
  // Set the active Paraglide locale before children resolve messages (SSR-safe:
  // synchronous, ahead of the children's render in this pass).
  setRouteLocale(locale as (typeof supportedLocales)[number])
  const value = useMemo<I18nContextType>(
    () => ({ locale, get, getEnumOptions }),
    [locale]
  )
  return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>
}
