// LocaleSwitcher — a minimal, SSR-safe language picker. Writes the canonical
// `voltro:locale` cookie the framework's auto-wired i18n resolver reads, then
// reloads so the server re-renders in the chosen locale. Same contract as
// <ProfileMenu>'s language switch, extracted for standalone use in any app that
// doesn't want the full profile menu (every scaffolded template drops this in).
//
// Native <select> on purpose: works everywhere with zero portal/positioning
// chrome, keyboard-accessible by default, and SSR-safe. Pass `current` (e.g.
// `useLocale()` from @voltro/i18n) so the server + first client paint agree on
// the selected option; without it the control hydrates from the cookie after
// mount (a brief flash from the first option, no hydration mismatch).

import {
  useEffect,
  useState,
  type ChangeEvent,
  type ReactNode,
} from 'react'
import { cn } from '../cn'
import { LOCALE_COOKIE, getCookie, setCookie } from '../cookies'

export interface LocaleOption {
  /** Language code written to the cookie (e.g. 'en', 'de'). */
  readonly code: string
  /** Human label shown in the picker (e.g. 'English', 'Deutsch'). */
  readonly label: string
}

export interface LocaleSwitcherProps {
  /** The languages to offer. */
  readonly locales: ReadonlyArray<LocaleOption>
  /** Override the active code. When omitted, hydrates from the `voltro:locale`
   *  cookie on mount (falling back to the first option until then). Pass
   *  `useLocale()` for a flash-free, mismatch-free control. */
  readonly current?: string
  /** Called with the chosen code before the reload. Return `false` to suppress
   *  the reload (e.g. when the consumer has a hot-swap i18n runtime). */
  readonly onChange?: (code: string) => boolean | void
  /** Accessible label for the control. Default `'Language'`. */
  readonly ariaLabel?: string
  readonly className?: string
}

export const LocaleSwitcher = ({
  locales,
  current,
  onChange,
  ariaLabel = 'Language',
  className,
}: LocaleSwitcherProps): ReactNode => {
  // Hydrate from the cookie on mount; `current` wins when set. The first client
  // render (before this effect) matches the server (both = first option when no
  // `current`), so hydration never mismatches — the cookie value lands as a
  // post-hydration controlled update.
  const [cookieLocale, setCookieLocale] = useState<string | undefined>(undefined)
  useEffect(() => {
    setCookieLocale(getCookie(LOCALE_COOKIE) ?? undefined)
  }, [])

  const active = current ?? cookieLocale ?? locales[0]?.code ?? ''

  const handle = (event: ChangeEvent<HTMLSelectElement>): void => {
    const next = event.target.value
    setCookie(LOCALE_COOKIE, next)
    setCookieLocale(next)
    const suppress = onChange?.(next) === false
    if (!suppress && typeof window !== 'undefined') window.location.reload()
  }

  return (
    <select
      aria-label={ariaLabel}
      value={active}
      onChange={handle}
      className={cn(
        'h-9 rounded-md border border-input bg-transparent px-2 text-sm shadow-xs ' +
          'outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:border-ring ' +
          'cursor-pointer',
        className,
      )}
    >
      {locales.map((l) => (
        <option key={l.code} value={l.code}>
          {l.label}
        </option>
      ))}
    </select>
  )
}
LocaleSwitcher.displayName = 'LocaleSwitcher'
