import fs from 'fs';
import path from 'path';

// Regex to find placeholders like {variableName}
const placeholderRegex = /\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;

interface Messages {
    [key: string]: string;
}

interface AllMessages {
    [lang: string]: Messages;
}

interface GenerateConfig {
    defaultLanguage: string;
    enabledLanguages: string[];
}

function getFileHeader(): string {
    return `/* Auto-generated by vite-plugin-messages - DO NOT EDIT */\n/* Generated: ${new Date().toISOString()} */\n`;
}

export function generateMessages(langDir: string, outDir: string, config: GenerateConfig) {
    const { defaultLanguage, enabledLanguages } = config;

    if (!fs.existsSync(outDir)) {
        fs.mkdirSync(outDir, { recursive: true });
    }

    const allMessages: AllMessages = {};

    for (const lang of enabledLanguages) {
        const filePath = path.join(langDir, `${lang}.json`);
        try {
            const content = fs.readFileSync(filePath, 'utf-8');
            allMessages[lang] = JSON.parse(content);
        } catch (e) {
            console.warn(`⚠️ Failed to load ${lang}.json:`, e instanceof Error ? e.message : String(e));
            allMessages[lang] = {};
        }
    }

    if (Object.keys(allMessages).length === 0) {
        console.warn('⚠️ No language files found');
        return;
    }

    const defaultMessages = allMessages[defaultLanguage] || {};
    const allKeys = Object.keys(defaultMessages);

    for (const lang of enabledLanguages) {
        const messages = allMessages[lang] || {};
        const functions: string[] = [];
        const reExports: string[] = [];

        for (const key of allKeys) {
            const hasTranslation = key in messages;

            if (hasTranslation) {
                functions.push(createMessageFunction(key, messages[key]));
            } else if (lang !== defaultLanguage) {
                reExports.push(key);
            }
        }

        let content = getFileHeader();

        if (reExports.length > 0) {
            content += `\nexport { ${reExports.join(', ')} } from './${defaultLanguage}.ts';\n`;
        }

        if (functions.length > 0) {
            content += `\n${functions.join('\n\n')}\n`;
        }

        const filePath = path.join(outDir, `${lang}.ts`);
        fs.writeFileSync(filePath, content, 'utf-8');
        console.log(`✅ Generated messages/${lang}.ts (${functions.length} translated, ${reExports.length} re-exported)`);
    }

    generateIndexFile(outDir, allKeys, defaultMessages, config);
}

function extractPlaceholders(value: string): string[] {
    const matches = value.matchAll(placeholderRegex);
    const placeholders = new Set<string>();
    for (const match of matches) {
        placeholders.add(match[1]);
    }
    return Array.from(placeholders);
}

function escapeTemplateString(value: string): string {
    // Escape backticks and ${} that are not our placeholders
    return value
        .replace(/\\/g, '\\\\')
        .replace(/`/g, '\\`');
}

function createMessageFunction(key: string, value: string): string {
    const placeholders = extractPlaceholders(value);
    const templateString = value.replace(placeholderRegex, '${params.$1}');
    const escapedTemplate = escapeTemplateString(templateString);

    if (placeholders.length > 0) {
        const paramsType = placeholders.map(p => `${p}: string | number`).join(', ');
        return `export const ${key} = (params: { ${paramsType} }): string => \`${escapedTemplate}\`;`;
    }
    return `export const ${key} = (): string => \`${escapedTemplate}\`;`;
}

function generateIndexFile(outDir: string, allKeys: string[], defaultMessages: Messages, config: GenerateConfig) {
    const { enabledLanguages } = config;

    const langImports = enabledLanguages
        .map(lang => `import * as ${lang} from './${lang}.ts';`)
        .join('\n');

    const langObject = enabledLanguages.join(', ');
    const languageType = enabledLanguages.map(l => `'${l}'`).join(' | ');
    const messageExports: string[] = [];

    for (const key of allKeys) {
        const value = defaultMessages[key] || '';
        const placeholders = extractPlaceholders(value);
        const paramsType = placeholders.length > 0
            ? `params: { ${placeholders.map(p => `${p}: string | number`).join(', ')} }`
            : '';
        const paramsArg = paramsType ? 'params' : '';

        messageExports.push(
            `export const ${key} = (${paramsType}): string => allMessages[getLocale()].${key}(${paramsArg});`
        );
    }

    const content = `${getFileHeader()}
import config from '@/config';

${langImports}

const allMessages = { ${langObject} } as const;

export type Language = ${languageType};

export const defaultLanguage: Language = '${config.defaultLanguage}';
export const enabledLanguages: readonly Language[] = ${JSON.stringify(config.enabledLanguages)} as const;

let _locale: Language = defaultLanguage;

export const getLocale = (): Language => _locale;
export const isValidLocale = (locale: unknown): locale is Language => enabledLanguages.includes(locale as Language);
export const setLocale = (locale: unknown): void => {
    if (isValidLocale(locale)) {
        _locale = locale as Language;
    }
};

// Message functions
${messageExports.join('\n\n')}
`;

    const filePath = path.join(outDir, 'index.ts');
    fs.writeFileSync(filePath, content, 'utf-8');
    console.log('✅ Generated messages/index.ts');
}
