import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// 常量配置
const CONSTANTS = {
	VUE_TEMPLATE_TAG: '<template',
	VUE_TEMPLATE_CLOSE_TAG: '</template>',
	VUE_TEMPLATE_TAG_LEN: 9,
	VUE_TEMPLATE_CLOSE_TAG_LEN: 11,
	VUE_TEMPLATE_MODULE: '?vue&type=template',
	VUE_SCRIPT_MODULE: '?vue&type=script',
	VUE_STYLE_MODULE: '?vue&type=style',
	FILE_EXTENSIONS: /\.(vue|js|ts|jsx|tsx)(\?.*)?$/,
	NON_ASCII_REGEX: /[^\x00-\x7F]/,
};

/**
 * 查找平衡括号的结束位置
 * @param {string} code - 代码字符串
 * @param {number} startPos - 起始位置（开括号之后）
 * @param {string} openChar - 开括号字符
 * @param {string} closeChar - 闭括号字符
 * @returns {number} 闭括号的位置，未找到返回 -1
 */
/**
 * 查找平衡括号的结束位置，正确处理字符串字面量中的括号
 * @param {string} code - 代码字符串
 * @param {number} startPos - 起始位置（开括号之后）
 * @param {string} openChar - 开括号字符
 * @param {string} closeChar - 闭括号字符
 * @returns {number} 闭括号的位置，未找到返回 -1
 */
function findBalancedBracket(code, startPos, openChar = '(', closeChar = ')') {
	let depth = 1;
	let pos = startPos;
	let inString = false;
	let stringChar = null;
	
	while (pos < code.length && depth > 0) {
		const char = code[pos];
		
		// 处理字符串字面量
		if (!inString && (char === '"' || char === "'")) {
			inString = true;
			stringChar = char;
		} else if (inString && char === stringChar) {
			// 检查是否是转义的引号：计算连续的反斜杠数量
			let backslashCount = 0;
			let checkPos = pos - 1;
			while (checkPos >= 0 && code[checkPos] === '\\') {
				backslashCount++;
				checkPos--;
			}
			// 如果反斜杠数量是偶数，则引号未转义，字符串结束
			if (backslashCount % 2 === 0) {
				inString = false;
				stringChar = null;
			}
		}
		
		// 只在非字符串中计算括号深度
		if (!inString) {
			if (char === openChar) depth++;
			else if (char === closeChar) {
				depth--;
				if (depth === 0) return pos;
			}
		}
		
		pos++;
	}
	
	return -1;
}

/**
 * 处理带参数的 t() 调用，支持 t('key') 和 t('key', { params })
 * @param {string} code - 源代码
 * @param {object} translations - 翻译字典
 * @returns {string} 处理后的代码
 */
function replaceTFunctionWithParams(code, translations) {
	const result = code.replace(
		/\bt\((['"])((?:\\.|(?!\1).)*)\1(?:,\s*(\{[^}]*\}))?\)/g,
		(match, quote, key, params) => {
			const unescapedKey = unescapeString(key);
			const translation = translations[unescapedKey];
			if (translation) {
				// 如果有参数，保持参数不变，只替换 key 部分
				const translated = quote + escapeString(translation, quote) + quote;
				return params ? `t(${translated},${params})` : `t(${translated})`;
			}
			return match;
		}
	);
	return result;
}

/**
 * 处理参数对象中的嵌套 $t() 调用
 * @param {string} paramsCode - 参数部分的代码
 * @param {object} translations - 翻译字典
 * @param {RegExp} pattern - 匹配 $t() 调用的正则表达式
 * @returns {string} 处理后的参数代码
 */
function processNestedTranslations(paramsCode, translations, pattern) {
	return paramsCode.replace(pattern, (match, ...args) => {
		// String.replace 回调的参数：match, ...captureGroups, index, input
		// 需要根据捕获组数量判断格式
		// 格式1: /([a-zA-Z_$][a-zA-Z0-9_$]*\.)?[\$]t\((['"])([^'"]+)\2\)/g -> 3个捕获组
		// 格式2: /\$t\((['"])([^'"]+)\1\)/g -> 2个捕获组
		// 格式3: /\{\{\s*[\$]t\s*\(\s*(['"])([^'"]+)\1\s*\)\s*\}\}/g -> 2个捕获组
		
		// 获取捕获组数量（排除最后两个参数：index 和 input）
		const captureGroups = args.slice(0, -2);
		let ctxPrefix = '';
		let quote;
		let key;
		
		if (captureGroups.length === 3) {
			// 格式1：带前缀的 (ctxPrefix, quote, key)
			ctxPrefix = captureGroups[0] || '';
			quote = captureGroups[1];
			key = unescapeString(captureGroups[2]);
		} else if (captureGroups.length === 2) {
			// 格式2或3：不带前缀的 (quote, key)
			quote = captureGroups[0];
			key = unescapeString(captureGroups[1]);
		} else {
			// 无法解析，返回原匹配
			return match;
		}
		
		const translation = translations[key];
		return translation 
			? `${ctxPrefix}$t(${quote}${escapeString(translation, quote)}${quote})` 
			: match;
	});
}

/**
 * Vite 插件：构建时直接读取 CSV，替换代码中的 $t('xxx') 为翻译文本
 * @param {object} options - 插件选项
 * @param {string} options.locale - 目标语言代码
 * @param {string} options.translationsPath - 翻译文件路径（相对于插件目录）
 * @param {string} options.defaultLocale - 默认语言代码
 */
function vitePluginTranslate(options = {}) {
	const locale = options.locale || 'en';
	const defaultLocale = options.defaultLocale || 'en';
	const translationsPath = options.translationsPath || '../jcloud/translations';
	
	// 在插件初始化时立即加载翻译数据，而不是等到 configResolved
	let translations = {};
	if (locale && locale !== defaultLocale) {
		const csvPath = path.resolve(__dirname, `${translationsPath}/${locale}.csv`);
		if (fs.existsSync(csvPath)) {
			try {
				translations = parseCSV(csvPath);
			} catch (error) {
				console.warn(`[vite-plugin-translate] Failed to load translations from ${csvPath}:`, error.message);
			}
		}
	}
	
	return {
		name: 'vite-plugin-translate',
		enforce: 'pre',
		configResolved(config) {
			// 确保翻译数据已加载（双重检查）
			if (locale && locale !== defaultLocale && Object.keys(translations).length === 0) {
				const csvPath = path.resolve(__dirname, `${translationsPath}/${locale}.csv`);
				if (fs.existsSync(csvPath)) {
					try {
						translations = parseCSV(csvPath);
					} catch (error) {
						console.warn(`[vite-plugin-translate] Failed to load translations from ${csvPath}:`, error.message);
					}
				}
			}
		},
		transform(code, id) {
			if (id.endsWith('index.html')) {
				const lang = locale;
				return {
					code: code.replace(/<html([^>]*)>/i, `<html$1 lang="${lang}">`),
					map: null
				};
			}
			
			const fileMatches = CONSTANTS.FILE_EXTENSIONS.test(id);
			if (!fileMatches || locale === defaultLocale || Object.keys(translations).length === 0) {
				return null;
			}
			
			const originalCode = code;
			const isVueFile = id.includes('.vue') && !id.includes(CONSTANTS.VUE_STYLE_MODULE);
			
			if (isVueFile) {
				const isTemplateModule = id.includes(CONSTANTS.VUE_TEMPLATE_MODULE);
				const isScriptModule = id.includes(CONSTANTS.VUE_SCRIPT_MODULE);
				
				if (isTemplateModule) {
					// Vue 编译后的模板模块
					code = replaceInterpolations(code, translations);
					code = replaceCompiledFormat(code, translations);
					code = replaceAttributeBindings(code, translations);
				} else if (isScriptModule) {
					// Vue 编译后的 script 模块 - 处理 this.$t() 和 $t() 调用
					// 注意：t() 函数调用已在原始 Vue SFC 文件中处理，编译后应该已经是翻译后的字符串
					code = code.replace(
						/(?:this\.)?\$t\((['"])((?:\\.|(?!\1).)*)\1\)/g,
						(match, quote, key) => {
							const unescapedKey = unescapeString(key);
							const translation = translations[unescapedKey];
							if (translation) {
								return quote + escapeString(translation, quote) + quote;
							}
							return match;
						}
					);
				} else {
					// 原始 Vue SFC 文件
					code = processVueSFC(code, translations);
				}
			} else {
				// 非 Vue 文件 - 支持带参数的 t() 调用
				code = replaceTFunctionWithParams(code, translations);
			}
			
			return code !== originalCode ? { code, map: null } : null;
		}
	};
}

/**
 * 处理 Vue SFC 文件
 */
function processVueSFC(code, translations) {
	// 处理 <template> 部分
	const templateRegex = /<template[^>]*>/gi;
	let templateMatch;
	
	while ((templateMatch = templateRegex.exec(code)) !== null) {
		const startIndex = templateMatch.index;
		const openTag = templateMatch[0];
		
		// 查找对应的 </template>，处理嵌套
		let depth = 1;
		let pos = templateRegex.lastIndex;
		let templateContent = '';
		
		while (depth > 0 && pos < code.length) {
			const nextOpen = code.indexOf(CONSTANTS.VUE_TEMPLATE_TAG, pos);
			const nextClose = code.indexOf(CONSTANTS.VUE_TEMPLATE_CLOSE_TAG, pos);
			
			if (nextClose === -1) break;
			
			if (nextOpen !== -1 && nextOpen < nextClose) {
				depth++;
				pos = nextOpen + CONSTANTS.VUE_TEMPLATE_TAG_LEN;
			} else {
				depth--;
				if (depth === 0) {
					templateContent = code.substring(templateRegex.lastIndex, nextClose);
					break;
				}
				pos = nextClose + CONSTANTS.VUE_TEMPLATE_CLOSE_TAG_LEN;
			}
		}
		
		if (depth === 0 && templateContent) {
			let replacedContent = templateContent;
			// 先处理属性绑定（包括带参数的），避免 replaceInterpolations 误处理
			replacedContent = replaceAttributeBindings(replacedContent, translations);
			// 处理属性绑定中的数组字面量，如 :items="[{ label: $t('key'), ... }]"
			replacedContent = replaceAttributeArrayLiterals(replacedContent, translations);
			// 处理属性绑定中的对象字面量，如 :options="{ title: $t('key'), ... }"
			replacedContent = replaceAttributeObjectLiterals(replacedContent, translations);
			// 最后处理插值表达式
			replacedContent = replaceInterpolations(replacedContent, translations);
			
			code = code.substring(0, startIndex) + openTag + replacedContent + CONSTANTS.VUE_TEMPLATE_CLOSE_TAG + 
				code.substring(startIndex + openTag.length + templateContent.length + CONSTANTS.VUE_TEMPLATE_CLOSE_TAG_LEN);
			break;
		}
	}
	
	// 处理 <script> 部分
	code = code.replace(
		/(<script[^>]*>)([\s\S]*?)(<\/script>)/gi,
		(match, openTag, scriptContent, closeTag) => {
			// 先处理 $t() 和 this.$t() 调用
			let replacedContent = scriptContent.replace(
				/(?:this\.)?\$t\((['"])((?:\\.|(?!\1).)*)\1\)/g,
				(match, quote, key) => {
					const unescapedKey = unescapeString(key);
					const translation = translations[unescapedKey];
					if (translation) {
						return quote + escapeString(translation, quote) + quote;
					}
					return match;
				}
			);
			
			// 再处理 t() 函数调用（从 i18n.js 导入的翻译函数）
			// 检查是否有从 i18n 导入 t 函数，或通过 useI18n composable 使用
			const hasTImport = /import\s*\{[^}]*\bt\b[^}]*\}\s*from\s*['"]\.\.?\/.*i18n['"]/i.test(scriptContent) ||
			                    /import\s*\{[^}]*\bt\b[^}]*\}\s*from\s*['"]@\/.*i18n['"]/i.test(scriptContent);
			
			// 检查是否通过 useI18n composable 使用 t 函数
			const hasUseI18n = /import\s*\{[^}]*useI18n[^}]*\}\s*from\s*['"]\.\.?\/.*useI18n['"]/i.test(scriptContent) ||
			                    /import\s*\{[^}]*useI18n[^}]*\}\s*from\s*['"]@\/.*useI18n['"]/i.test(scriptContent) ||
			                    /const\s*\{[^}]*\bt\b[^}]*\}\s*=\s*useI18n\(\)/i.test(scriptContent);
			
			if (hasTImport || hasUseI18n) {
				// 匹配 t('key') 或 t("key")，但排除 t.something() 或 t['something']()
				replacedContent = replacedContent.replace(
					/\bt\((['"])((?:\\.|(?!\1).)*)\1\)/g,
					(match, quote, key) => {
						const unescapedKey = unescapeString(key);
						const translation = translations[unescapedKey];
						if (translation) {
							return quote + escapeString(translation, quote) + quote;
						}
						return match;
					}
				);
			}
			
			return openTag + replacedContent + closeTag;
		}
	);
	
	return code;
}

/**
 * 替换插值表达式 {{ $t('xxx') }} 或 {{ $t('xxx', { ... }) }}
 */
function replaceInterpolations(code, translations) {
	// 先处理不带参数的调用：{{ $t('xxx') }}
	code = code.replace(
		/\{\{\s*[\$]t\s*\(\s*(['"])((?:\\.|(?!\1).)*)\1\s*\)\s*\}\}/g,
		(match, quote, key) => {
			const unescapedKey = unescapeString(key);
			return translations[unescapedKey] || match;
		}
	);
	
	// 处理插值表达式内部的 $t() 调用（不在单独的 {{ $t(...) }} 中）
	// 例如：{{ condition ? $t('key1') : $t('key2') }}
	// 注意：跳过属性绑定中的内容（它们会在 replaceAttributeBindings 中处理）
	code = code.replace(
		/\{\{[\s\S]*?\}\}/g,
		(interpolation, offset, string) => {
			// 检查这个插值是否在属性绑定中（前后有 = 和引号）
			const beforeMatch = string.substring(Math.max(0, offset - 20), offset);
			const afterMatch = string.substring(offset + interpolation.length, Math.min(string.length, offset + interpolation.length + 20));
			if (/[=:]["']\s*$/.test(beforeMatch) || /^["']\s*[>\/\s]/.test(afterMatch)) {
				// 在属性绑定中，跳过处理
				return interpolation;
			}
			
			// 如果这个插值已经是一个完整的 {{ $t(...) }}，跳过
			if (/^\{\{\s*[\$]t\s*\(/.test(interpolation.trim())) {
				return interpolation;
			}
			// 否则，处理其中的 $t() 调用
			return interpolation.replace(
				/\$t\((['"])((?:\\.|(?!\1).)*)\1\)/g,
				(match, quote, key) => {
					const unescapedKey = unescapeString(key);
					const translation = translations[unescapedKey];
					return translation ? `$t(${quote}${escapeString(translation, quote)}${quote})` : match;
				}
			);
		}
	);
	
	// 处理带参数的调用：{{ $t('key', { params }) }}
	const matches = [];
	const pattern = /\{\{\s*[\$]t\s*\(\s*(['"])((?:\\.|(?!\1).)*)\1\s*,\s*/g;
	let match;
	
	while ((match = pattern.exec(code)) !== null) {
		const startIndex = match.index;
		const quote = match[1];
		const key = unescapeString(match[2]);
		const afterKeyIndex = match.index + match[0].length;
		
		// 找到参数部分的结束位置
		const paramsEnd = findBalancedBracket(code, afterKeyIndex);
		if (paramsEnd === -1) continue;
		
		// 找到整个 {{ $t(...) }} 的结束位置
		let fullEnd = paramsEnd + 1;
		while (fullEnd < code.length && code[fullEnd] === ' ') fullEnd++;
		if (fullEnd < code.length && code[fullEnd] === '}') {
			fullEnd++;
			if (fullEnd < code.length && code[fullEnd] === '}') fullEnd++;
		}
		
		matches.push({ startIndex, quote, key, afterKeyIndex, paramsEnd, fullEnd });
	}
	
	// 从后往前替换，避免索引错乱
	for (let i = matches.length - 1; i >= 0; i--) {
		const m = matches[i];
		let paramsPart = code.substring(m.afterKeyIndex, m.paramsEnd);
		
		// 处理参数部分中的嵌套 $t() 调用
		// 先处理 {{ $t(...) }} 格式（模板插值）
		paramsPart = processNestedTranslations(
			paramsPart,
			translations,
			/\{\{\s*[\$]t\s*\(\s*(['"])((?:\\.|(?!\1).)*)\1\s*\)\s*\}\}/g
		);
		// 再处理 $t(...) 格式（参数对象中的直接调用）
		paramsPart = processNestedTranslations(
			paramsPart,
			translations,
			/\$t\((['"])((?:\\.|(?!\1).)*)\1\)/g
		);
		
		const translation = translations[m.key];
		if (translation) {
			const replacement = `{{ $t(${m.quote}${escapeString(translation, m.quote)}${m.quote}, ${paramsPart}) }}`;
			code = code.substring(0, m.startIndex) + replacement + code.substring(m.fullEnd);
		}
	}
	
	return code;
}

/**
 * 替换 Vue 编译后的格式：_ctx.$t('xxx') 或 $t('xxx')，支持带参数
 */
function replaceCompiledFormat(code, translations) {
	// 处理带参数的调用
	const matches = [];
	const pattern = /([a-zA-Z_$][a-zA-Z0-9_$]*\.)?[\$]t\((['"])((?:\\.|(?!\2).)*)\2\s*,\s*/g;
	let match;
	
	while ((match = pattern.exec(code)) !== null) {
		const startIndex = match.index;
		const ctxPrefix = match[1] || '';
		const quote = match[2];
		const key = unescapeString(match[3]);
		const afterKeyIndex = match.index + match[0].length;
		
		const paramsEnd = findBalancedBracket(code, afterKeyIndex);
		if (paramsEnd === -1) continue;
		
		matches.push({ startIndex, ctxPrefix, quote, key, afterKeyIndex, paramsEnd });
	}
	
	// 从后往前替换
	for (let i = matches.length - 1; i >= 0; i--) {
		const m = matches[i];
		let paramsPart = code.substring(m.afterKeyIndex, m.paramsEnd);
		
		// 处理参数部分中的嵌套 $t() 调用
		paramsPart = processNestedTranslations(
			paramsPart,
			translations,
			/([a-zA-Z_$][a-zA-Z0-9_$]*\.)?[\$]t\((['"])((?:\\.|(?!\2).)*)\2\)/g
		);
		
		const translation = translations[m.key];
		if (translation) {
			const replacement = `${m.ctxPrefix}$t(${m.quote}${escapeString(translation, m.quote)}${m.quote}, ${paramsPart})`;
			code = code.substring(0, m.startIndex) + replacement + code.substring(m.paramsEnd + 1);
		}
	}
	
	// 处理不带参数的调用
	code = code.replace(
		/([a-zA-Z_$][a-zA-Z0-9_$]*\.)?[\$]t\((['"])((?:\\.|(?!\2).)*)\2\)/g,
		(match, ctxPrefix, quote, key) => {
			const unescapedKey = unescapeString(key);
			const translation = translations[unescapedKey];
			return translation ? `${ctxPrefix || ''}$t(${quote}${escapeString(translation, quote)}${quote})` : match;
		}
	);
	
	return code;
}

/**
 * 替换属性绑定中的 $t('xxx') 或 $t('xxx', { params })
 */
function replaceAttributeBindings(code, translations) {
	// 先处理带参数的调用：:label="$t('key', { params })"
	const matches = [];
	const pattern = /([:@]|v-bind:|v-on:)([a-zA-Z0-9_-]+)=(["'])[\$]?t\((['"])((?:\\.|(?!\4).)*)\4\s*,\s*/g;
	let match;
	
	while ((match = pattern.exec(code)) !== null) {
		const startIndex = match.index;
		const prefix = match[1];
		const attrName = match[2];
		const outerQuote = match[3];
		const innerQuote = match[4];
		const key = unescapeString(match[5]);
		const afterKeyIndex = match.index + match[0].length;
		
		// 找到参数部分的结束位置（闭括号）
		const paramsEnd = findBalancedBracket(code, afterKeyIndex);
		if (paramsEnd === -1) continue;
		
		// 找到整个属性绑定的结束位置（匹配外层的引号）
		let attrEnd = paramsEnd + 1;
		while (attrEnd < code.length && (code[attrEnd] === ' ' || code[attrEnd] === '\t' || code[attrEnd] === '\n')) attrEnd++;
		if (attrEnd < code.length && code[attrEnd] === outerQuote) {
			attrEnd++;
		}
		
		matches.push({ startIndex, prefix, attrName, outerQuote, innerQuote, key, afterKeyIndex, paramsEnd, attrEnd });
	}
	
	// 从后往前替换，避免索引错乱
	for (let i = matches.length - 1; i >= 0; i--) {
		const m = matches[i];
		let paramsPart = code.substring(m.afterKeyIndex, m.paramsEnd);
		
		// 处理参数部分中的嵌套 $t() 调用
		paramsPart = processNestedTranslations(
			paramsPart,
			translations,
			/\$t\((['"])((?:\\.|(?!\1).)*)\1\)/g
		);
		
		const translation = translations[m.key];
		if (translation) {
			// 转义翻译文本以适配内层引号
			let escaped = escapeString(translation, m.innerQuote);
			// 保留 $t() 调用结构，只替换翻译键
			const replacement = `${m.prefix}${m.attrName}=${m.outerQuote}$t(${m.innerQuote}${escaped}${m.innerQuote}, ${paramsPart})${m.outerQuote}`;
			code = code.substring(0, m.startIndex) + replacement + code.substring(m.attrEnd);
		}
	}
	
	// 再处理不带参数的调用：:label="$t('key')"
	// 统一处理逻辑：保留 $t() 调用结构，只替换翻译键（与带参数的处理保持一致）
	return code.replace(
		/([:@]|v-bind:|v-on:)([a-zA-Z0-9_-]+)=(["'])[\$]?t\((['"])((?:\\.|(?!\4).)*)\4\)\3/g,
		(match, prefix, attrName, outerQuote, innerQuote, key) => {
			const unescapedKey = unescapeString(key);
			const translation = translations[unescapedKey];
			if (!translation || !translation.trim()) return match;
			
			// 转义翻译文本以适配内层引号（与带参数的处理保持一致）
			const escaped = escapeString(translation, innerQuote);
			// 保留 $t() 调用结构，只替换翻译键
			return `${prefix}${attrName}=${outerQuote}$t(${innerQuote}${escaped}${innerQuote})${outerQuote}`;
		}
	);
}

/**
 * 在代码片段中替换所有 $t() 调用为翻译文本
 * @param {string} content - 要处理的代码片段
 * @param {object} translations - 翻译字典
 * @param {RegExp} pattern - 可选的匹配模式，默认匹配所有 $t() 调用
 * @returns {string} 替换后的代码
 */
function replaceTranslationCalls(content, translations, pattern = /\$t\((['"])((?:\\.|(?!\1).)*)\1\)/g) {
	return content.replace(pattern, (match, quote, key) => {
		const unescapedKey = unescapeString(key);
		const translation = translations[unescapedKey];
		if (!translation || !translation.trim()) return match;
		const escaped = escapeString(translation, quote);
		return `${quote}${escaped}${quote}`;
	});
}

/**
 * 替换属性绑定中数组字面量内的 $t('xxx')
 * 例如：:items="[{ label: $t('key'), ... }]"
 */
function replaceAttributeArrayLiterals(code, translations) {
	// 匹配属性绑定中的数组字面量，如 :items="[...]"
	// 使用更宽松的匹配，支持单引号和双引号
	return code.replace(
		/([:@]|v-bind:|v-on:)([a-zA-Z0-9_-]+)=(["'])\[([\s\S]*?)\]\3/g,
		(match, prefix, attrName, outerQuote, arrayContent) => {
			const replacedContent = replaceTranslationCalls(arrayContent, translations);
			return `${prefix}${attrName}=${outerQuote}[${replacedContent}]${outerQuote}`;
		}
	);
}

/**
 * 替换属性绑定中对象字面量内的 $t('xxx')
 * 例如：:options="{ title: $t('key'), actions: [...] }"
 */
function replaceAttributeObjectLiterals(code, translations) {
	// 匹配属性绑定中的对象字面量，使用平衡括号匹配以正确处理嵌套
	const pattern = /([:@]|v-bind:|v-on:)([a-zA-Z0-9_-]+)=(["'])\{/g;
	const matches = [];
	let match;
	
	while ((match = pattern.exec(code)) !== null) {
		const startIndex = match.index;
		const prefix = match[1];
		const attrName = match[2];
		const outerQuote = match[3];
		const openBraceIndex = startIndex + match[0].length - 1; // 开括号的位置
		const afterBraceIndex = openBraceIndex + 1; // 开括号之后的位置
		
		// 找到匹配的闭合大括号
		let depth = 1;
		let pos = afterBraceIndex;
		let braceEnd = -1;
		
		while (pos < code.length && depth > 0) {
			const char = code[pos];
			// 跳过字符串字面量中的大括号
			if (char === '"' || char === "'") {
				pos++;
				// 跳过转义的引号
				while (pos < code.length && (code[pos] !== char || code[pos - 1] === '\\')) {
					pos++;
				}
				pos++;
				continue;
			}
			
			if (char === '{') depth++;
			else if (char === '}') {
				depth--;
				if (depth === 0) {
					braceEnd = pos;
					break;
				}
			}
			pos++;
		}
		
		if (braceEnd === -1) continue;
		
		// 检查是否以相同的引号结束
		if (braceEnd + 1 < code.length && code[braceEnd + 1] === outerQuote) {
			const objectContent = code.substring(afterBraceIndex, braceEnd);
			matches.push({ startIndex, prefix, attrName, outerQuote, afterBraceIndex, braceEnd, objectContent });
		}
	}
	
	// 从后往前替换，避免索引错乱
	for (let i = matches.length - 1; i >= 0; i--) {
		const m = matches[i];
		// 匹配对象属性值中的 $t()，支持键名（标识符或字符串）
		const replacedContent = m.objectContent.replace(
			/(['"]?\w+['"]?\s*:\s*)\$t\((['"])((?:\\.|(?!\2).)*)\2\)/g,
			(match, keyPrefix, quote, key) => {
				const unescapedKey = unescapeString(key);
				const translation = translations[unescapedKey];
				if (!translation || !translation.trim()) return match;
				const escaped = escapeString(translation, quote);
				return `${keyPrefix}${quote}${escaped}${quote}`;
			}
		);
		const replacement = `${m.prefix}${m.attrName}=${m.outerQuote}{${replacedContent}}${m.outerQuote}`;
		code = code.substring(0, m.startIndex) + replacement + code.substring(m.braceEnd + 2);
	}
	
	return code;
}

/**
 * 去除字符串中的转义字符（将 \' 转换为 '，\" 转换为 " 等）
 */
function unescapeString(text) {
	return text
		.replace(/\\(.)/g, '$1');
}

/**
 * 转义字符串
 */
function escapeString(text, quote) {
	return text
		.replace(/\\/g, '\\\\')
		.replace(quote === '"' ? /"/g : /'/g, quote === '"' ? '\\"' : "\\'");
}

/**
 * 解析 CSV 文件
 * 格式：key,translation,context
 * 支持包含逗号的键（通过检测非ASCII字符识别翻译部分）
 */
function parseCSV(csvPath) {
	if (!fs.existsSync(csvPath)) {
		return {};
	}
	
	const content = fs.readFileSync(csvPath, 'utf-8');
	const lines = content.split('\n');
	const translations = {};
	
	for (const line of lines) {
		const trimmed = line.trim();
		if (!trimmed || trimmed.startsWith('#')) continue;
		
		// 标准 CSV 解析（支持引号）
		// 只有当字段以引号开始时，引号才作为 CSV 格式的引号处理
		const parts = [];
		let current = '';
		let inQuotes = false;
		let fieldStartedWithQuote = false;
		
		for (let i = 0; i < trimmed.length; i++) {
			const char = trimmed[i];
			if (char === '"') {
				// 如果当前字段还没开始（current 为空），且这是字段的第一个字符，标记为引号包裹的字段
				if (current === '' && !inQuotes) {
					fieldStartedWithQuote = true;
					inQuotes = true;
					// 不将开始的引号添加到 current
				} else if (inQuotes && fieldStartedWithQuote) {
					// 在引号包裹的字段中，处理转义的引号 "" 或结束引号
					if (i + 1 < trimmed.length && trimmed[i + 1] === '"') {
						current += '"';
						i++;
					} else {
						// 结束引号，不添加到 current
						inQuotes = false;
						fieldStartedWithQuote = false;
					}
				} else {
					// 不在引号包裹的字段中，引号是内容的一部分
					current += char;
				}
			} else if (char === ',' && !inQuotes) {
				parts.push(current);
				current = '';
				fieldStartedWithQuote = false;
			} else {
				current += char;
			}
		}
		parts.push(current);
		
		// 如果解析出的部分超过2个，可能是键中包含逗号但没有引号
		// 通过检测非ASCII字符来识别翻译部分
		if (parts.length > 2) {
			let translationIndex = -1;
			for (let i = parts.length - 1; i >= 0; i--) {
				if (parts[i] && CONSTANTS.NON_ASCII_REGEX.test(parts[i])) {
					translationIndex = i;
					break;
				}
			}
			
			if (translationIndex > 0) {
				const key = parts.slice(0, translationIndex).join(',').trim();
				const translation = parts[translationIndex].trim();
				translations[key] = translation;
				continue;
			}
		}
		
		if (parts.length >= 2 && parts[0] && parts[1]) {
			const key = parts[0].trim();
			const translation = parts[1].trim();
			const context = parts[2] ? parts[2].trim() : '';
			
			translations[context ? `${key}:${context}` : key] = translation;
		}
	}
	
	return translations;
}

export default vitePluginTranslate;
