/**
 * Script to find missing translations in locale files
 *
 * Usage:
 *   node scripts/find-missing-translations.js [options]
 *
 * Options:
 *   --locale=<locale>   Only check a specific locale (e.g. --locale=fr)
 *   --file=<file>       Only check a specific file (e.g. --file=chat.json)
 *   --help              Show this help message
 */

const fs = require("fs")
const path = require("path")

// Process command line arguments
const args = process.argv.slice(2).reduce((acc, arg) => {
	if (arg === "--help") {
		acc.help = true
	} else if (arg.startsWith("--locale=")) {
		acc.locale = arg.split("=")[1]
	} else if (arg.startsWith("--file=")) {
		acc.file = arg.split("=")[1]
	}
	return acc
}, {})

// Show help if requested
if (args.help) {
	console.log(`
Find Missing Translations

A utility script to identify missing translations across locale files.
Compares non-English locale files to the English ones to find any missing keys.

Usage: 
  node scripts/find-missing-translations.js [options]

Options:
  --locale=<locale>   Only check a specific locale (e.g. --locale=fr)
  --file=<file>       Only check a specific file (e.g. --file=chat.json)
  --help              Show this help message

Output:
  - Generates a report of missing translations
  `)
	process.exit(0)
}

// Path to the locales directory
const LOCALES_DIR = path.join(__dirname, "../webview-ui/src/i18n/locales")

// Recursively find all keys in an object
function findKeys(obj, parentKey = "") {
	let keys = []

	for (const [key, value] of Object.entries(obj)) {
		const currentKey = parentKey ? `${parentKey}.${key}` : key

		if (typeof value === "object" && value !== null) {
			// If value is an object, recurse
			keys = [...keys, ...findKeys(value, currentKey)]
		} else {
			// If value is a primitive, add the key
			keys.push(currentKey)
		}
	}

	return keys
}

// Get value at a dotted path in an object
function getValueAtPath(obj, path) {
	const parts = path.split(".")
	let current = obj

	for (const part of parts) {
		if (current === undefined || current === null) {
			return undefined
		}
		current = current[part]
	}

	return current
}

// Main function to find missing translations
function findMissingTranslations() {
	try {
		// Get all locale directories (or filter to the specified locale)
		const allLocales = fs.readdirSync(LOCALES_DIR).filter((item) => {
			const stats = fs.statSync(path.join(LOCALES_DIR, item))
			return stats.isDirectory() && item !== "en" // Exclude English as it's our source
		})

		// Filter to the specified locale if provided
		const locales = args.locale ? allLocales.filter((locale) => locale === args.locale) : allLocales

		if (args.locale && locales.length === 0) {
			console.error(`Error: Locale '${args.locale}' not found in ${LOCALES_DIR}`)
			process.exit(1)
		}

		console.log(`Checking ${locales.length} non-English locale(s): ${locales.join(", ")}`)

		// Get all English JSON files
		const englishDir = path.join(LOCALES_DIR, "en")
		let englishFiles = fs.readdirSync(englishDir).filter((file) => file.endsWith(".json") && !file.startsWith("."))

		// Filter to the specified file if provided
		if (args.file) {
			if (!englishFiles.includes(args.file)) {
				console.error(`Error: File '${args.file}' not found in ${englishDir}`)
				process.exit(1)
			}
			englishFiles = englishFiles.filter((file) => file === args.file)
		}

		// Load file contents
		const englishFileContents = englishFiles.map((file) => ({
			name: file,
			content: JSON.parse(fs.readFileSync(path.join(englishDir, file), "utf8")),
		}))

		console.log(
			`Checking ${englishFileContents.length} translation file(s): ${englishFileContents.map((f) => f.name).join(", ")}`,
		)

		// Results object to store missing translations
		const missingTranslations = {}

		// For each locale, check for missing translations
		for (const locale of locales) {
			missingTranslations[locale] = {}

			for (const { name, content: englishContent } of englishFileContents) {
				const localeFilePath = path.join(LOCALES_DIR, locale, name)

				// Check if the file exists in the locale
				if (!fs.existsSync(localeFilePath)) {
					missingTranslations[locale][name] = { file: "File is missing entirely" }
					continue
				}

				// Load the locale file
				const localeContent = JSON.parse(fs.readFileSync(localeFilePath, "utf8"))

				// Find all keys in the English file
				const englishKeys = findKeys(englishContent)

				// Check for missing keys in the locale file
				const missingKeys = []

				for (const key of englishKeys) {
					const englishValue = getValueAtPath(englishContent, key)
					const localeValue = getValueAtPath(localeContent, key)

					if (localeValue === undefined) {
						missingKeys.push({
							key,
							englishValue,
						})
					}
				}

				if (missingKeys.length > 0) {
					missingTranslations[locale][name] = missingKeys
				}
			}
		}

		// Output results
		let hasMissingTranslations = false

		console.log("\nMissing Translations Report:\n")

		for (const [locale, files] of Object.entries(missingTranslations)) {
			if (Object.keys(files).length === 0) {
				console.log(`✅ ${locale}: No missing translations`)
				continue
			}

			hasMissingTranslations = true
			console.log(`📝 ${locale}:`)

			for (const [fileName, missingItems] of Object.entries(files)) {
				if (missingItems.file) {
					console.log(`  - ${fileName}: ${missingItems.file}`)
					continue
				}

				console.log(`  - ${fileName}: ${missingItems.length} missing translations`)

				for (const { key, englishValue } of missingItems) {
					console.log(`      ${key}: "${englishValue}"`)
				}
			}

			console.log("")
		}

		if (!hasMissingTranslations) {
			console.log("\n✅ All translations are complete!")
		} else {
			console.log("✏️  To add missing translations:")
			console.log("1. Add the missing keys to the corresponding locale files")
			console.log("2. Translate the English values to the appropriate language")
			console.log("3. Run this script again to verify all translations are complete")
		}
	} catch (error) {
		console.error("Error:", error.message)
		console.error(error.stack)
		process.exit(1)
	}
}

// Run the main function
findMissingTranslations()
