"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.i18nRules = void 0;
/**
 * i18n Rules — Deterministic checks for internationalization coverage and sync
 */
const path = __importStar(require("path"));
function diag(rule, filePath, message, opts = {}) {
    return {
        ruleId: rule.id,
        filePath,
        line: opts.line,
        severity: rule.severity,
        message,
        help: opts.help || rule.help,
        autoFixable: opts.autoFixable ?? false,
    };
}
// ─── Rules ────────────────────────────────────────────────────────
const PROJECT_TYPES = ["nextjs", "turbo", "node"];
const i18nConfigured = {
    id: "i18n/configured",
    name: "i18n Configured",
    category: "i18n",
    severity: "warning",
    description: "Check if i18n is configured in .mycontext/config.json",
    help: "Run 'mycontext init' to configure i18n or manually add it to config.json",
    appliesTo: PROJECT_TYPES,
    async check(ctx) {
        const results = [];
        const config = await ctx.readJson(".mycontext/config.json");
        if (!config?.i18n) {
            results.push(diag(this, ".mycontext/config.json", "i18n is not configured for this project"));
        }
        return results;
    },
};
const dictionariesExist = {
    id: "i18n/dictionaries-exist",
    name: "Dictionaries Exist",
    category: "i18n",
    severity: "error",
    description: "Verify that configured i18n dictionaries actually exist",
    help: "Create the dictionary files in the path specified in config.json",
    appliesTo: PROJECT_TYPES,
    async check(ctx) {
        const results = [];
        const config = await ctx.readJson(".mycontext/config.json");
        const i18n = config?.i18n;
        if (!i18n)
            return results;
        for (const locale of i18n.locales) {
            const dictPath = path.join(i18n.dictionaryPath, `${locale}.json`);
            if (!(await ctx.fileExists(dictPath))) {
                results.push(diag(this, dictPath, `Missing dictionary file for locale: ${locale}`));
            }
        }
        return results;
    },
};
const hardcodedStrings = {
    id: "i18n/no-hardcoded-strings",
    name: "No Hardcoded Strings",
    category: "i18n",
    severity: "warning",
    description: "Detect hardcoded strings in components that should be localized",
    help: "Move strings to i18n dictionaries and use translate hooks (e.g., t('key'))",
    appliesTo: PROJECT_TYPES,
    async check(ctx) {
        const results = [];
        const config = await ctx.readJson(".mycontext/config.json");
        if (!config?.i18n)
            return results;
        // Use findFiles to get components
        const allTsx = await ctx.findFiles(/\.tsx$/);
        const componentFiles = allTsx.filter(f => !f.includes("components/ui/") && // Skip shadcn UI
            !f.includes(".stories."));
        for (const filePath of componentFiles) {
            const content = await ctx.readFile(filePath);
            if (!content)
                continue;
            const hardcodedRegex = />([^<>{}\n\r]+)</g;
            let match;
            while ((match = hardcodedRegex.exec(content)) !== null) {
                const capturedText = match[1];
                if (!capturedText)
                    continue;
                const text = capturedText.trim();
                if (text.length > 3 && /[a-zA-Z]/.test(text) && !text.includes("import ") && !text.includes("export ")) {
                    const lines = content.substring(0, match.index).split("\n");
                    results.push(diag(this, filePath, `Potential hardcoded string found: "${text}"`, { line: lines.length }));
                }
            }
        }
        return results;
    },
};
const dictionarySync = {
    id: "i18n/dictionary-sync",
    name: "Dictionary Key Sync",
    category: "i18n",
    severity: "error",
    description: "Ensure all locales have the same keys in their dictionaries",
    help: "Sync missing keys between dictionary files",
    appliesTo: PROJECT_TYPES,
    async check(ctx) {
        const results = [];
        const config = await ctx.readJson(".mycontext/config.json");
        const i18n = config?.i18n;
        if (!i18n || i18n.locales.length < 2)
            return results;
        const defaultDict = await ctx.readJson(path.join(i18n.dictionaryPath, `${i18n.defaultLocale}.json`));
        if (!defaultDict)
            return results;
        const defaultKeys = new Set(Object.keys(flattenObject(defaultDict)));
        for (const locale of i18n.locales) {
            if (locale === i18n.defaultLocale)
                continue;
            const dictPath = path.join(i18n.dictionaryPath, `${locale}.json`);
            const dict = await ctx.readJson(dictPath);
            if (!dict)
                continue;
            const keys = new Set(Object.keys(flattenObject(dict)));
            const missing = [...defaultKeys].filter(k => !keys.has(k));
            if (missing.length > 0) {
                results.push(diag(this, dictPath, `Locale "${locale}" is missing keys from "${i18n.defaultLocale}": ${missing.slice(0, 3).join(", ")}${missing.length > 3 ? "..." : ""}`));
            }
        }
        return results;
    },
};
function flattenObject(obj, prefix = "") {
    return Object.keys(obj).reduce((acc, k) => {
        const pre = prefix.length ? prefix + "." : "";
        if (typeof obj[k] === "object" && obj[k] !== null && !Array.isArray(obj[k])) {
            Object.assign(acc, flattenObject(obj[k], pre + k));
        }
        else {
            acc[pre + k] = obj[k];
        }
        return acc;
    }, {});
}
exports.i18nRules = [
    i18nConfigured,
    dictionariesExist,
    hardcodedStrings,
    dictionarySync,
];
//# sourceMappingURL=i18n-rules.js.map