/**
 * Runtime language switch — German default, English on request.
 *
 * WHY NOT @nuxtjs/i18n
 * --------------------
 * This site is 12 components, 4 pages and one form. @nuxtjs/i18n would pull in vue-i18n
 * plus a build-time message transform, and its route strategies want to own the URL
 * space (`/en/...`) — which would break every in-page anchor (`/#vorteil`) and every
 * link that already exists, for no gain. A typed message catalogue plus this composable
 * is ~40 lines of runtime code, adds nothing to the dependency tree, and keeps the
 * language on ONE url so a shared link always works.
 *
 * SSR CORRECTNESS
 * ---------------
 * The active locale lives in `useState`, so it is resolved exactly once on the server,
 * serialised into the payload and re-used verbatim during hydration — there is no
 * second, client-side resolution that could disagree with the server render, which is
 * the usual source of hydration mismatches in hand-rolled i18n.
 *
 * PRECEDENCE:  ?lang=  →  cookie  →  Accept-Language  →  German.
 * `?lang=` is what makes a language linkable and testable with plain curl; whatever it
 * resolves to is written back to the cookie, so the choice survives the next visit.
 */
import {
  DEFAULT_LOCALE,
  isLocale,
  localeFromAcceptLanguage,
  messages,
  type Locale,
  type Messages,
} from '~/locales'

export const LOCALE_COOKIE = 'b24_lang'
const LOCALE_STATE = 'b24-locale'
const ONE_YEAR = 60 * 60 * 24 * 365

export const useLocale = () => {
  const cookie = useCookie<string | null>(LOCALE_COOKIE, {
    maxAge: ONE_YEAR,
    sameSite: 'lax',
    path: '/',
  })

  // Resolved here, during setup, rather than inside setLocale: a click handler runs
  // outside the component's setup context, and these are Nuxt composables.
  const route = useRoute()
  const router = useRouter()

  const locale = useState<Locale>(LOCALE_STATE, () => {
    // 1 · explicit ?lang= wins, so a language can be linked to and curl'd.
    const requested = route.query.lang
    const fromQuery = Array.isArray(requested) ? requested[0] : requested
    if (isLocale(fromQuery)) return fromQuery

    // 2 · the visitor's stored choice.
    if (isLocale(cookie.value)) return cookie.value

    // 3 · browser preference, German winning whenever it is ambiguous.
    if (import.meta.server) {
      const header = useRequestHeaders(['accept-language'])['accept-language'] || ''
      return localeFromAcceptLanguage(header)
    }
    return DEFAULT_LOCALE
  })

  // Persist a ?lang= (or header-derived) resolution. No-op once they agree, so this
  // does not write a cookie on every component that calls useLocale().
  if (cookie.value !== locale.value) cookie.value = locale.value

  const t = computed<Messages>(() => messages[locale.value] ?? messages[DEFAULT_LOCALE])
  const isGerman = computed(() => locale.value === 'de')
  const isEnglish = computed(() => locale.value === 'en')

  const setLocale = (next: Locale) => {
    if (!isLocale(next) || next === locale.value) return
    locale.value = next
    cookie.value = next

    // Drop a `?lang=` that is now contradicted by the choice just made. Without this the
    // switch works, but reloading the page would silently undo it — `?lang=` outranks the
    // cookie by design. Same URL otherwise, so nothing else about the page changes.
    if (!import.meta.client) return
    if (!('lang' in route.query)) return
    const { lang: _dropped, ...rest } = route.query
    router.replace({ path: route.path, query: rest, hash: route.hash })
  }

  return { locale, t, isGerman, isEnglish, setLocale }
}
