"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectConventions = detectConventions;
exports.ensureConventionTable = ensureConventionTable;
exports.recordCloudConvention = recordCloudConvention;
exports.getCloudConventions = getCloudConventions;
exports.getCloudConventionStats = getCloudConventionStats;
const database_1 = require("../../06-memory/database/database");
function inferNamingConvention(patterns) {
    const hasEquals = (s) => s.includes('=');
    const extractName = (s) => {
        const parts = s.split(/[=:]/);
        const namePart = parts[0].trim().replace(/^(const|let|var)\s+/, '');
        return namePart;
    };
    const camelCase = patterns.filter((p) => {
        if (!hasEquals(p.to))
            return false;
        const name = extractName(p.to);
        return /^[a-z][a-zA-Z0-9]*$/.test(name);
    });
    const snakeCase = patterns.filter((p) => {
        const name = extractName(p.to);
        return /^[a-z]+_[a-z0-9]+(_[a-z0-9]+)*$/.test(name) || /^[a-z]+_[a-z0-9]+(_[a-z0-9]+)*$/.test(extractName(p.from));
    });
    const pascalCase = patterns.filter((p) => {
        if (!hasEquals(p.to))
            return false;
        const name = extractName(p.to);
        return /^[A-Z][a-zA-Z0-9]*$/.test(name);
    });
    const max = Math.max(camelCase.length, snakeCase.length, pascalCase.length);
    if (max < 2)
        return null;
    let name = 'camelCase';
    let confidence = camelCase.length / Math.max(camelCase.length + snakeCase.length + pascalCase.length, 1);
    if (snakeCase.length > camelCase.length && snakeCase.length > pascalCase.length) {
        name = 'snake_case';
        confidence = snakeCase.length / Math.max(camelCase.length + snakeCase.length + pascalCase.length, 1);
    }
    else if (pascalCase.length > camelCase.length && pascalCase.length > snakeCase.length) {
        name = 'PascalCase';
        confidence = pascalCase.length / Math.max(camelCase.length + snakeCase.length + pascalCase.length, 1);
    }
    return {
        id: `conv-naming-${name}`,
        type: 'naming',
        name: `${name} naming`,
        description: `Project predominantly uses ${name} naming convention`,
        confidence: Math.round(confidence * 100) / 100,
        evidenceCount: max,
        examples: patterns.slice(0, 3).map((p) => ({ from: p.from, to: p.to })),
        category: 'naming',
        severity: confidence >= 0.8 ? 'adopted' : confidence >= 0.5 ? 'emerging' : 'inconsistent',
    };
}
function inferFormattingConvention(patterns) {
    const hasArrow = patterns.filter((p) => p.to.includes('=>') || p.to.includes('() =>'));
    const hasFunction = patterns.filter((p) => p.to.startsWith('function'));
    if (hasArrow.length + hasFunction.length < 2)
        return null;
    const total = hasArrow.length + hasFunction.length;
    const arrowPct = hasArrow.length / total;
    return {
        id: arrowPct >= 0.5 ? 'conv-format-arrow' : 'conv-format-function',
        type: 'formatting',
        name: arrowPct >= 0.5 ? 'arrow functions preferred' : 'function declarations preferred',
        description: arrowPct >= 0.5
            ? 'Project prefers arrow functions over function declarations'
            : 'Project prefers function declarations over arrow functions',
        confidence: Math.round(Math.max(arrowPct, 1 - arrowPct) * 100) / 100,
        evidenceCount: total,
        examples: patterns.slice(0, 3).map((p) => ({ from: p.from, to: p.to })),
        category: 'formatting',
        severity: Math.max(arrowPct, 1 - arrowPct) >= 0.8 ? 'adopted' : Math.max(arrowPct, 1 - arrowPct) >= 0.6 ? 'emerging' : 'inconsistent',
    };
}
function inferStructuralConvention(patterns) {
    const hasConst = patterns.filter((p) => p.to.includes('const ') && !p.to.includes('let ') && !p.to.includes('var '));
    const hasLet = patterns.filter((p) => p.to.includes('let '));
    const hasVar = patterns.filter((p) => p.to.includes('var '));
    const total = hasConst.length + hasLet.length + hasVar.length;
    if (total < 2)
        return null;
    let name = 'const preferred';
    let count = hasConst.length;
    if (hasLet.length > count) {
        name = 'let preferred';
        count = hasLet.length;
    }
    if (hasVar.length > count) {
        name = 'var preferred';
        count = hasVar.length;
    }
    return {
        id: `conv-struct-${name.replace(/\s+/g, '-')}`,
        type: 'structure',
        name,
        description: `Project predominantly uses ${name} for variable declarations`,
        confidence: Math.round(count / total * 100) / 100,
        evidenceCount: total,
        examples: patterns.filter((p) => /const|let|var/.test(p.to)).slice(0, 3).map((p) => ({ from: p.from, to: p.to })),
        category: 'variable_declaration',
        severity: count / total >= 0.8 ? 'adopted' : count / total >= 0.6 ? 'emerging' : 'inconsistent',
    };
}
function detectConventions(projectId, patterns) {
    const conventions = [];
    const inconsistencies = [];
    const naming = inferNamingConvention(patterns);
    const formatting = inferFormattingConvention(patterns);
    const structural = inferStructuralConvention(patterns);
    if (naming)
        conventions.push(naming);
    if (formatting)
        conventions.push(formatting);
    if (structural)
        conventions.push(structural);
    // Detect inconsistencies: patterns that contradict each other
    const varPatterns = patterns.filter((p) => /const|let|var/.test(p.category));
    for (let i = 0; i < varPatterns.length; i++) {
        for (let j = i + 1; j < varPatterns.length; j++) {
            const a = varPatterns[i];
            const b = varPatterns[j];
            if ((a.to.includes('const') && b.to.includes('let') && a.from.includes('let') && b.from.includes('const')) ||
                (a.to.includes('let') && b.to.includes('const') && a.from.includes('const') && b.from.includes('let'))) {
                inconsistencies.push({
                    a: a.patternId,
                    b: b.patternId,
                    description: `Contradictory declaration preferences: "${a.description}" vs "${b.description}"`,
                    patterns: [a.patternId, b.patternId],
                });
            }
        }
    }
    const dominantStyle = naming?.name || formatting?.name || structural?.name || 'mixed';
    return {
        projectId,
        conventions,
        inconsistencies,
        dominantStyle,
        generatedAt: Date.now(),
    };
}
// ─── CLOUD CONVENTION DB (SQLite) ──────────────────────
function ensureConventionTable() {
    const db = (0, database_1.getDb)();
    db.exec(`CREATE TABLE IF NOT EXISTS conventions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    project_id TEXT NOT NULL,
    category TEXT NOT NULL,
    convention TEXT NOT NULL,
    count INT NOT NULL DEFAULT 1
  )`);
}
function recordCloudConvention(projectId, category, convention) {
    const db = (0, database_1.getDb)();
    const existing = db.prepare(`SELECT id, count FROM conventions WHERE project_id = ? AND category = ? AND convention = ?`).get(projectId, category, convention);
    if (existing) {
        db.prepare(`UPDATE conventions SET count = ? WHERE id = ?`).run(existing.count + 1, existing.id);
    }
    else {
        db.prepare(`INSERT INTO conventions (project_id, category, convention, count) VALUES (?, ?, ?, 1)`).run(projectId, category, convention);
    }
}
function getCloudConventions(projectId) {
    const db = (0, database_1.getDb)();
    const rows = db.prepare(`SELECT category, convention, count FROM conventions WHERE project_id = ? ORDER BY count DESC`).all(projectId);
    return rows.map(r => ({ category: r.category, convention: r.convention, count: r.count }));
}
function getCloudConventionStats() {
    const db = (0, database_1.getDb)();
    const total = db.prepare(`SELECT COUNT(*) as total FROM conventions`).get()?.total || 0;
    const perProject = db.prepare(`SELECT project_id, COUNT(*) as count FROM conventions GROUP BY project_id`).all();
    return { totalConventions: total, perProject };
}
//# sourceMappingURL=convention-detector.js.map