/**
 * Generates `src/common/intl/locales.generated.ts` from the Twosky language
 * list in `.twosky.json` (project: `home_v2`).
 *
 * Usage:
 *   node ./scripts/generate-locales.js      # regenerate the file
 *   npm run locales:generate               # same, via package.json
 *
 * CI freshness guard:
 *   npm run locales:check                  # fails if output is stale
 *
 * The generated file contains static import statements and a LOCALES map so
 * that webpack can tree-shake each locale JSON bundle.  Every locale from
 * `.twosky.json` → `home_v2.languages` is included except those listed in
 * EXCLUDES below.
 */

import { readFileSync, writeFileSync } from 'node:fs';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

// --- Configuration ---

const __dirname = dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = resolve(__dirname, '..', '..');
const TWOSKY_PATH = resolve(REPO_ROOT, '.twosky.json');

// Allow the caller to override the output path via `--out <path>`.
// Useful for CI checks that want to generate to a temp file.
const args = process.argv.slice(2);
const outFlagIdx = args.indexOf('--out');
const OUTPUT_PATH =
    outFlagIdx !== -1 && args[outFlagIdx + 1]
        ? resolve(args[outFlagIdx + 1])
        : resolve(__dirname, '..', 'src', 'common', 'intl', 'locales.generated.ts');

// --- Helpers ---

/** Turn a hyphenated locale code into a valid JavaScript identifier.
 *  E.g. "pt-br" → "ptBr",  "zh-hk" → "zhHk",  "sr-cs" → "srCs".
 */
const toAlias = (code) => code.replace(/-([a-z])/g, (_, c) => c.toUpperCase());

// --- Main ---

try {
    const twoskyRaw = readFileSync(TWOSKY_PATH, 'utf-8');
    const twosky = JSON.parse(twoskyRaw);

    const homeV2 = twosky.find((p) => p.project_id === 'home_v2');
    if (!homeV2) {
        console.error('ERROR: no project with project_id "home_v2" found in .twosky.json');
        process.exit(1);
    }

    const allCodes = Object.keys(homeV2.languages);
    // Stable sort for deterministic output
    allCodes.sort();

    // Verify every locale JSON file exists before writing output
    const localesDir = resolve(__dirname, '..', 'src', '__locales');
    for (const code of allCodes) {
        const jsonPath = resolve(localesDir, `${code}.json`);
        try {
            readFileSync(jsonPath);
        } catch {
            console.error(
                `ERROR: locale JSON file not found: ${jsonPath}` +
                    `\n  Ensure the file was downloaded from Twosky before regenerating.`,
            );
            process.exit(1);
        }
    }

    // --- Emit ---

    const baseLocale = homeV2.base_locale || 'en';
    const lazyCodes = allCodes.filter((code) => code !== baseLocale);

    const lines = [
        '/* eslint-disable */',
        '// AUTO-GENERATED by `npm run locales:generate`.  Do not edit by hand.',
        '// Source: .twosky.json → project_id: home_v2 → languages',
        '// Excludes: (none)',
        '',
        'export type LocaleMessage = Record<string, string>;',
        '',
    ];

    // Static import for the base locale (always bundled, synchronous fallback)
    const baseAlias = toAlias(baseLocale);
    lines.push(`import ${baseAlias} from 'panel/__locales/${baseLocale}.json';`);
    lines.push('');

    // Lazy-loaders for every non-base locale.
    // Return type is Promise<any> because JSON dynamic imports produce
    // { default: LocaleMessage }; the preloadLocale() helper unwraps
    // the .default at runtime.
    lines.push('export const LOCALE_LOADERS: Record<string, () => Promise<any>> = {');
    for (let i = 0; i < lazyCodes.length; i++) {
        const code = lazyCodes[i];
        const comma = i === lazyCodes.length - 1 ? '' : ',';
        lines.push(
            `    '${code}': () => import(/* webpackChunkName: "locale.${code}" */ 'panel/__locales/${code}.json')${comma}`,
        );
    }
    lines.push('};');
    lines.push('');

    // All known locale codes (used by resolveLanguage to validate codes
    // before messages are loaded)
    const codeList = allCodes.map((c) => `'${c}'`).join(', ');
    lines.push(`export const LOCALE_CODES = new Set([${codeList}]);`);
    lines.push('');

    // Synchronously available locale data — starts with only the base
    // locale, expanded by preloadLocale() at runtime.
    lines.push('export const LOCALES: Record<string, LocaleMessage> = {');
    lines.push(`    ${baseLocale}: ${baseAlias},`);
    lines.push('};');
    lines.push('');

    writeFileSync(OUTPUT_PATH, lines.join('\n') + '\n', 'utf-8');

    console.log(`Wrote ${OUTPUT_PATH} (${allCodes.length} locales)`);
} catch (err) {
    console.error('Failed to generate locales.generated.ts:', err.message);
    process.exit(1);
}
