import type { Locale } from "discord.js"
import frLocale from "@/locales/fr.json"
import enLocale from "@/locales/en.json"
import dbGuild from "@/schemas/guild"
import { logConsoleError } from "./console"

// Variables d'environnement pour les locales avec valeurs par défaut
const DEFAULT_LOCALE = process.env.DEFAULT_LOCALE ?? 'fr'
const CONSOLE_LOCALE = process.env.CONSOLE_LOCALE ?? 'en'

// Types pour l'internationalisation
type LocaleData = Record<string, unknown>
type ReplacementParams = Record<string, string | number>
type TranslationKey = string

/**
 * Récupère la locale configurée pour un serveur
 * @param guildId - L'ID du serveur Discord
 * @returns La locale configurée ou 'fr' par défaut
 */
export async function getGuildLocale(guildId: string): Promise<string> {
	try {
		const guildProfile = await dbGuild.findOne({ guildId })
		return guildProfile?.guildLocale ?? 'fr'
	} catch (error) {
		logConsoleError('mongoose', 'locale.fetch_error', { guildId }, error as Error)
		return 'fr'
	}
}

// Conversion des imports en type LocaleData
const frLocaleData = frLocale as unknown as LocaleData
const enLocaleData = enLocale as unknown as LocaleData

// Locales supportées
const locales = {
	'fr': frLocaleData,
	'en-US': enLocaleData,
	'en-GB': enLocaleData
} as const

type SupportedLocale = keyof typeof locales

/**
 * Récupère une traduction basée sur la locale et la clé
 */
function getNestedValue(obj: LocaleData, path: string): string | undefined {
	try {
		const keys = path.split('.')
		let current: unknown = obj
		
		for (const key of keys) {
			if (current !== null && typeof current === 'object' && key in current) current = (current as Record<string, unknown>)[key]
			else return undefined
		}
		
		return typeof current === 'string' ? current : undefined
	} catch { return undefined }
}

/**
 * Remplace les paramètres dans une chaîne de caractères
 * Exemple: "Hello {name}" avec {name: "World"} devient "Hello World"
 */
function replaceParams(text: string, params: ReplacementParams = {}): string {
	return text.replace(/\{(\w+)\}/g, (match, key: string) => {
		if (Object.prototype.hasOwnProperty.call(params, key)) return params[key].toString()
		return match
	})
}

/**
 * Fonction principale de localisation
 * @param locale - La locale Discord de l'utilisateur
 * @param key - La clé de traduction (ex: "player.not_in_voice")
 * @param params - Les paramètres à remplacer dans la traduction
 * @returns La chaîne traduite
 */
export function t(locale: Locale | string, key: TranslationKey, params: ReplacementParams = {}): string {
	// Détermine la locale à utiliser (par défaut de la config)
	const supportedLocale: SupportedLocale = (Object.keys(locales).includes(locale)) ? locale as SupportedLocale : DEFAULT_LOCALE as SupportedLocale
	
	// Récupère les données de locale
	const localeData = locales[supportedLocale]
	
	// Récupère la traduction
	const translation = getNestedValue(localeData, key)
	
	if (!translation) {
		console.warn(`[Localization] Translation not found for key: ${key} in locale: ${supportedLocale}`)
		return key // Retourne la clé si la traduction n'est pas trouvée
	}
	
	// Remplace les paramètres et retourne la traduction
	return replaceParams(translation, params)
}

/**
 * Fonction helper pour obtenir la locale française par défaut
 */
export function fr(key: TranslationKey, params: ReplacementParams = {}): string {
	return t('fr', key, params)
}

/**
 * Fonction helper pour obtenir la locale anglaise
 */
export function en(key: TranslationKey, params: ReplacementParams = {}): string {
	return t('en-US', key, params)
}

/**
 * Obtient les locales supportées pour une commande
 * Utilisé pour les localisations des commandes slash
 */
export function getCommandLocalizations(baseKey: string) {
	return {
		fr: getNestedValue(frLocaleData, baseKey) ?? baseKey,
		'en-US': getNestedValue(enLocaleData, baseKey) ?? baseKey,
		'en-GB': getNestedValue(enLocaleData, baseKey) ?? baseKey
	}
}

/**
 * Fonction de localisation utilisant la locale du serveur
 * @param guildLocale - La locale configurée du serveur
 * @param key - La clé de traduction (ex: "player.not_in_voice")
 * @param params - Les paramètres à remplacer dans la traduction
 * @returns La chaîne traduite
 */
export function tGuild(guildLocale: string, key: TranslationKey, params: ReplacementParams = {}): string {
	return t(guildLocale, key, params)
}

/**
 * Fonction helper pour obtenir la locale appropriée (serveur ou utilisateur)
 * @param guildId - L'ID du serveur (optionnel)
 * @param userLocale - La locale de l'utilisateur
 * @returns La locale à utiliser
 */
export async function getLocaleForContext(guildId: string | null, userLocale: string): Promise<string> {
	if (guildId) return await getGuildLocale(guildId)
	return userLocale
}

/**
 * Fonction de traduction intelligente qui utilise automatiquement la locale du serveur
 * @param interaction - L'interaction Discord
 * @param key - La clé de traduction
 * @param params - Les paramètres de remplacement
 * @returns La chaîne traduite
 */
export async function tSmart(interaction: { guild: { id: string } | null; locale: string }, key: TranslationKey, params: ReplacementParams = {}): Promise<string> {
	const locale = await getLocaleForContext(interaction.guild?.id ?? null, interaction.locale)
	return t(locale, key, params)
}

// Export des constantes de locale
export { DEFAULT_LOCALE, CONSOLE_LOCALE }

// Export des types pour utilisation externe
export type { TranslationKey, ReplacementParams, SupportedLocale }
