import type { Composer, I18n } from 'vue-i18n'
import { createI18n as createVueI18n } from 'vue-i18n'
import en from './locales/en.json'
import es from './locales/es.json'
import fr from './locales/fr.json'
import he from './locales/he.json'
import it from './locales/it.json'
import ru from './locales/ru.json'

export type MessageSchema = typeof en

// Bagelink's built-in locales
const bagelinkLocales = {
	en,
	he,
	it,
	es,
	fr,
	ru,
} as const

export interface CreateBagelI18nOptions {
	/** Active locale (default: 'en'). Same as vue-i18n's `locale`. */
	locale?: string
	/** Fallback locale (default: 'en'). Same as vue-i18n's `fallbackLocale`. */
	fallbackLocale?: string
	/** User's custom messages merged with bagelink's built-in translations. Same as vue-i18n's `messages`. */
	messages?: Record<string, Record<string, unknown>>
}

let i18nInstance: I18n | null = null

/**
 * Creates an i18n instance with bagelink's translations merged with user's.
 * Options mirror vue-i18n's `createI18n` for consistency.
 */
export function createI18n(options: CreateBagelI18nOptions = {}): I18n {
	const {
		locale = 'en',
		fallbackLocale = 'en',
		messages = {},
	} = options

	// Merge bagelink locales with user messages for all supported locales
	const supportedLocales = Object.keys(bagelinkLocales)
	const mergedMessages: Record<string, Record<string, unknown>> = {}

	for (const lang of supportedLocales) {
		mergedMessages[lang] = {
			...(bagelinkLocales[lang as keyof typeof bagelinkLocales] || {}),
			...(messages[lang] || {}),
		}
	}

	// Also include any user-provided locales not in bagelink's built-ins
	for (const lang of Object.keys(messages)) {
		if (!mergedMessages[lang]) {
			mergedMessages[lang] = messages[lang]
		}
	}

	i18nInstance = createVueI18n({
		locale,
		fallbackLocale,
		messages: mergedMessages as any,
		legacy: false,
		globalInjection: true,
	})

	return i18nInstance
}

/**
 * Get the global i18n instance
 */
export function getI18n(): I18n {
	if (!i18nInstance) {
		throw new Error('i18n not initialized. Call createI18n() first.')
	}
	return i18nInstance
}

interface UseI18nReturn {
	$t: Composer['t']
	t: Composer['t']
	locale: Composer['locale']
	availableLocales: Composer['availableLocales']
	fallbackLocale: Composer['fallbackLocale']
	n: Composer['n']
	d: Composer['d']
}

/**
 * useI18n wrapper that returns bagelink's typed i18n functions.
 * Uses the global i18n instance directly to work in all contexts,
 * including dialog containers mounted in a secondary app instance.
 */
export function useI18n(): UseI18nReturn {
	const global = getI18n().global as Composer

	return {
		$t: global.t,
		t: global.t,
		locale: global.locale,
		availableLocales: global.availableLocales,
		fallbackLocale: global.fallbackLocale,
		n: global.n,
		d: global.d,
	}
}

// Export locale data for direct access if needed
export { bagelinkLocales }

/**
 * A string that is either a plain string or a translation key prefixed with `$t:`.
 * @example
 * 'Save'           // plain string, used as-is
 * '$t:btn.save'    // translation key, resolved via i18n
 */
export type TranslatableString = string | `$t:${string}`

/**
 * Resolves a TranslatableString.
 * If the value starts with `$t:`, it's treated as a translation key.
 * Otherwise the string is returned as-is.
 * Works outside component context (uses the global i18n instance).
 *
 * @example
 * resolveI18n('Save')              // → 'Save'
 * resolveI18n('$t:btn.save')       // → 'Salva' (if locale is 'it')
 * resolveI18n(undefined)           // → undefined
 */
export function resolveI18n(value: TranslatableString | undefined): string | undefined {
	if (value == null) return undefined
	if (!value.startsWith('$t:')) return value
	return (getI18n().global.t as (key: string) => string)(value.slice(3))
}
