"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SyntaxEngine = void 0;
const cell_store_1 = require("../walls/06-memory/stores/cell-store");
class SyntaxEngine {
    store;
    data;
    constructor(cellDir) {
        this.store = new cell_store_1.CellStore(cellDir);
        this.data = this.store.read('syntax.json', 'personal', 'style') || {
            version: 1, updated: Date.now(),
            functionNaming: { getter: 0, handler: 0, setter: 0, boolean: 0, creator: 0, other: 0, topPatterns: [] },
            componentNaming: { pascalCase: 0, nonPascal: 0, consistency: 0 },
            constantNaming: { screamingSnake: 0, camelCase: 0, preference: 'unknown' },
            asyncStyle: { awaitCount: 0, thenCount: 0, preference: 'unknown' },
            destructuring: { objectDestruct: 0, arrayDestruct: 0, totalAssignments: 0, usageRate: 0 },
            optionalChaining: { dotAccess: 0, chainAccess: 0, usageRate: 0 },
            nullishCoalescing: { usageCount: 0, orCount: 0, preference: 'unknown' },
            templateLiterals: { templateCount: 0, concatCount: 0, preference: 'unknown' },
            semicolons: { withSemicolon: 0, withoutSemicolon: 0, consistency: 0, preference: 'unknown' },
            quotes: { singleQuotes: 0, doubleQuotes: 0, templateQuotes: 0, preference: 'unknown' },
            trailingCommas: { withComma: 0, withoutComma: 0, consistency: 0, preference: 'unknown' },
            comments: { lineComments: 0, blockComments: 0, totalFunctions: 0, commentRate: 0 },
            structure: { avgFunctionLength: 0, totalFunctions: 0, singleResponsibility: 0 },
        };
    }
    analyze(code) {
        if (!code || code.length < 20)
            return { patternsFound: 0 };
        let found = 0;
        found += this.analyzeFunctionNaming(code);
        found += this.analyzeComponentNaming(code);
        found += this.analyzeConstantNaming(code);
        found += this.analyzeAsyncStyle(code);
        found += this.analyzeDestructuring(code);
        found += this.analyzeOptionalChaining(code);
        found += this.analyzeNullishCoalescing(code);
        found += this.analyzeTemplateLiterals(code);
        found += this.analyzeSemicolons(code);
        found += this.analyzeQuotes(code);
        found += this.analyzeTrailingCommas(code);
        found += this.analyzeComments(code);
        found += this.analyzeStructure(code);
        if (found > 0) {
            this.data.updated = Date.now();
            this.store.write('syntax.json', this.data, 'personal', 'style');
        }
        return { patternsFound: found };
    }
    // ─── Function Naming ────────────────────────────────
    analyzeFunctionNaming(code) {
        const funcs = code.match(/(?:function\s+(\w+)|const\s+(\w+)\s*[:=]\s*(?:async\s*)?\(|(\w+)\s*=\s*(?:async\s*)?\([^)]*\)\s*=>)/g);
        if (!funcs)
            return 0;
        const names = [];
        for (const f of funcs) {
            const m = f.match(/function\s+(\w+)/) || f.match(/const\s+(\w+)/);
            if (m)
                names.push(m[1]);
        }
        const patterns = {};
        for (const n of names) {
            if (/^(get|fetch|load|find|read)\w+/i.test(n))
                patterns.getter = (patterns.getter || 0) + 1;
            else if (/^(handle|on)\w+/i.test(n))
                patterns.handler = (patterns.handler || 0) + 1;
            else if (/^(set|update|put|save)\w+/i.test(n))
                patterns.setter = (patterns.setter || 0) + 1;
            else if (/^(is|has|should|can|will)\w+/i.test(n))
                patterns.boolean = (patterns.boolean || 0) + 1;
            else if (/^(create|build|generate|make)\w+/i.test(n))
                patterns.creator = (patterns.creator || 0) + 1;
            else
                patterns.other = (patterns.other || 0) + 1;
        }
        this.data.functionNaming.getter += patterns.getter || 0;
        this.data.functionNaming.handler += patterns.handler || 0;
        this.data.functionNaming.setter += patterns.setter || 0;
        this.data.functionNaming.boolean += patterns.boolean || 0;
        this.data.functionNaming.creator += patterns.creator || 0;
        this.data.functionNaming.other += patterns.other || 0;
        const top = Object.entries(patterns).sort((a, b) => b[1] - a[1]).slice(0, 3);
        for (const [k] of top) {
            if (!this.data.functionNaming.topPatterns.includes(k))
                this.data.functionNaming.topPatterns.push(k);
        }
        return names.length;
    }
    // ─── Component Naming ───────────────────────────────
    analyzeComponentNaming(code) {
        const comps = code.match(/export\s+(?:default\s+)?(?:function|const)\s+(\w+)/g);
        if (!comps)
            return 0;
        for (const c of comps) {
            const m = c.match(/(\w+)$/);
            if (m) {
                if (/^[A-Z][a-z]/.test(m[1]))
                    this.data.componentNaming.pascalCase++;
                else
                    this.data.componentNaming.nonPascal++;
            }
        }
        const total = this.data.componentNaming.pascalCase + this.data.componentNaming.nonPascal;
        this.data.componentNaming.consistency = total > 0 ? Math.round(this.data.componentNaming.pascalCase / total * 100) : 0;
        return comps.length;
    }
    // ─── Constants Naming ───────────────────────────────
    analyzeConstantNaming(code) {
        const consts = code.match(/\bconst\s+(\w+)\s*=/g);
        if (!consts)
            return 0;
        for (const c of consts) {
            const m = c.match(/\bconst\s+(\w+)/);
            if (m) {
                if (/^[A-Z][A-Z_\d]+$/.test(m[1]))
                    this.data.constantNaming.screamingSnake++;
                else
                    this.data.constantNaming.camelCase++;
            }
        }
        const total = this.data.constantNaming.screamingSnake + this.data.constantNaming.camelCase;
        if (total > 0) {
            const ssPct = this.data.constantNaming.screamingSnake / total;
            this.data.constantNaming.preference = ssPct > 0.3 ? 'UPPER_CASE' : 'camelCase';
        }
        return consts.length;
    }
    // ─── Async Style ────────────────────────────────────
    analyzeAsyncStyle(code) {
        const awaitMatches = (code.match(/\bawait\b/g) || []).length;
        const thenMatches = (code.match(/\.then\s*\(/g) || []).length;
        if (awaitMatches > 0 || thenMatches > 0) {
            this.data.asyncStyle.awaitCount += awaitMatches;
            this.data.asyncStyle.thenCount += thenMatches;
            const total = this.data.asyncStyle.awaitCount + this.data.asyncStyle.thenCount;
            if (total > 0) {
                const awaitPct = this.data.asyncStyle.awaitCount / total;
                this.data.asyncStyle.preference = awaitPct > 0.5 ? 'async/await' : '.then() chains';
            }
            return 1;
        }
        return 0;
    }
    // ─── Destructuring ──────────────────────────────────
    analyzeDestructuring(code) {
        const objDestruct = (code.match(/\{\s*\w+\s*[,}]\s*\w*\s*\}/g) || []).length;
        const arrDestruct = (code.match(/\[\s*\w+\s*[,}\]]/g) || []).length;
        const assigns = (code.match(/\w+\s*=\s*/g) || []).length;
        if (objDestruct > 0 || arrDestruct > 0) {
            this.data.destructuring.objectDestruct += objDestruct;
            this.data.destructuring.arrayDestruct += arrDestruct;
            this.data.destructuring.totalAssignments += assigns;
            this.data.destructuring.usageRate = this.data.destructuring.totalAssignments > 0
                ? Math.round((this.data.destructuring.objectDestruct + this.data.destructuring.arrayDestruct) / this.data.destructuring.totalAssignments * 100) : 0;
            return 1;
        }
        return 0;
    }
    // ─── Optional Chaining ──────────────────────────────
    analyzeOptionalChaining(code) {
        const chainAccess = (code.match(/\?\./g) || []).length;
        const dotAccess = (code.match(/\.\w+/g) || []).length;
        if (chainAccess > 0) {
            this.data.optionalChaining.chainAccess += chainAccess;
            this.data.optionalChaining.dotAccess += dotAccess;
            this.data.optionalChaining.usageRate = dotAccess > 0
                ? Math.round(chainAccess / dotAccess * 100) : 0;
            return 1;
        }
        return 0;
    }
    // ─── Nullish Coalescing ─────────────────────────────
    analyzeNullishCoalescing(code) {
        const nullishCoal = (code.match(/\?\?\s/g) || []).length;
        const orFallback = (code.match(/\|\|\s/g) || []).length;
        if (nullishCoal > 0 || orFallback > 0) {
            this.data.nullishCoalescing.usageCount += nullishCoal;
            this.data.nullishCoalescing.orCount += orFallback;
            const total = this.data.nullishCoalescing.usageCount + this.data.nullishCoalescing.orCount;
            this.data.nullishCoalescing.preference = total > 0 && (this.data.nullishCoalescing.usageCount / total > 0.3)
                ? '?? (nullish coalescing)' : '|| (OR fallback)';
            return 1;
        }
        return 0;
    }
    // ─── Template Literals ──────────────────────────────
    analyzeTemplateLiterals(code) {
        const templates = (code.match(/`[^`]*\$\{[^`]*`/g) || []).length;
        const concats = (code.match(/['"`]\s*\+\s*['"`]/g) || []).length;
        if (templates > 0 || concats > 0) {
            this.data.templateLiterals.templateCount += templates;
            this.data.templateLiterals.concatCount += concats;
            const total = this.data.templateLiterals.templateCount + this.data.templateLiterals.concatCount;
            this.data.templateLiterals.preference = total > 0 && this.data.templateLiterals.templateCount > this.data.templateLiterals.concatCount
                ? 'template literals' : 'string concatenation';
            return 1;
        }
        return 0;
    }
    // ─── Semicolons ─────────────────────────────────────
    analyzeSemicolons(code) {
        const lines = code.split('\n').filter(l => {
            const t = l.trim();
            return t && !t.startsWith('//') && !t.startsWith('*') && !t.startsWith('{') && !t.startsWith('}') && !t.startsWith('#') && !t.startsWith('import');
        });
        if (lines.length < 2)
            return 0;
        let withSemi = 0;
        let withoutSemi = 0;
        for (const l of lines) {
            const t = l.trim();
            // Only count lines that are clearly statements (not closing braces)
            if (/^[}\])]/.test(t))
                continue;
            if (/[;]\s*$/.test(t))
                withSemi++;
            else if (/[a-zA-Z0-9`'"]\s*$/.test(t) && !/^[}\])]/.test(t))
                withoutSemi++;
        }
        this.data.semicolons.withSemicolon = Math.round((this.data.semicolons.withSemicolon + withSemi) / 2);
        this.data.semicolons.withoutSemicolon = Math.round((this.data.semicolons.withoutSemicolon + withoutSemi) / 2);
        const total = this.data.semicolons.withSemicolon + this.data.semicolons.withoutSemicolon;
        if (total > 0) {
            this.data.semicolons.consistency = Math.round(Math.max(this.data.semicolons.withSemicolon, this.data.semicolons.withoutSemicolon) / total * 100);
            this.data.semicolons.preference = this.data.semicolons.withSemicolon > this.data.semicolons.withoutSemicolon * 1.2 ? 'with semicolons' : (this.data.semicolons.withoutSemicolon > this.data.semicolons.withSemicolon * 1.2 ? 'no semicolons' : 'unknown');
        }
        return 1;
    }
    // ─── Quotes ─────────────────────────────────────────
    analyzeQuotes(code) {
        const singleQuotes = (code.match(/'[^']*'/g) || []).length;
        const doubleQuotes = (code.match(/"([^"]*)"/g) || []).length;
        if (singleQuotes > 0 || doubleQuotes > 0) {
            this.data.quotes.singleQuotes = Math.round((this.data.quotes.singleQuotes + singleQuotes) / 2);
            this.data.quotes.doubleQuotes = Math.round((this.data.quotes.doubleQuotes + doubleQuotes) / 2);
            const total = this.data.quotes.singleQuotes + this.data.quotes.doubleQuotes;
            this.data.quotes.preference = total > 0 && singleQuotes > doubleQuotes ? 'single quotes' : 'double quotes';
            return 1;
        }
        return 0;
    }
    // ─── Trailing Commas ────────────────────────────────
    analyzeTrailingCommas(code) {
        const trailingCommas = (code.match(/,(\s*\/\/.*)?\s*[\])}]/g) || []).length;
        const noTrailing = (code.match(/[^,]\s*[\])}]/g) || []).length;
        if (trailingCommas > 0 || noTrailing > 0) {
            this.data.trailingCommas.withComma += trailingCommas;
            this.data.trailingCommas.withoutComma += noTrailing;
            const total = this.data.trailingCommas.withComma + this.data.trailingCommas.withoutComma;
            if (total > 0) {
                this.data.trailingCommas.consistency = Math.round(Math.max(this.data.trailingCommas.withComma, this.data.trailingCommas.withoutComma) / total * 100);
                this.data.trailingCommas.preference = this.data.trailingCommas.withComma > this.data.trailingCommas.withoutComma ? 'trailing commas' : 'no trailing commas';
            }
            return 1;
        }
        return 0;
    }
    // ─── Comments ───────────────────────────────────────
    analyzeComments(code) {
        const lineComments = (code.match(/\/\/\s/g) || []).length;
        const blockComments = (code.match(/\/\*/g) || []).length;
        const functions = (code.match(/(?:function\s+\w+|=>|\([^)]*\)\s*=>)/g) || []).length;
        if (functions > 0 || lineComments > 0) {
            this.data.comments.lineComments += lineComments;
            this.data.comments.blockComments += blockComments;
            this.data.comments.totalFunctions += functions;
            this.data.comments.commentRate = functions > 0 ? Math.round((lineComments + blockComments * 3) / functions * 100) / 100 : 0;
            return 1;
        }
        return 0;
    }
    // ─── Structure ──────────────────────────────────────
    analyzeStructure(code) {
        const functions = code.match(/(?:function\s+\w+|=>\s*\{|\([^)]*\)\s*=>)/g);
        if (!functions)
            return 0;
        const totalFuncs = functions.length;
        let totalLines = 0;
        for (const f of functions) {
            const idx = code.indexOf(f);
            const braceStart = code.indexOf('{', idx);
            if (braceStart > 0) {
                let depth = 0;
                let braceEnd = -1;
                for (let i = braceStart; i < code.length; i++) {
                    if (code[i] === '{')
                        depth++;
                    if (code[i] === '}') {
                        depth--;
                        if (depth === 0) {
                            braceEnd = i;
                            break;
                        }
                    }
                }
                if (braceEnd > 0)
                    totalLines += code.slice(braceStart, braceEnd + 1).split('\n').length;
            }
        }
        const avgLen = totalFuncs > 0 ? Math.round(totalLines / totalFuncs) : 0;
        const prevTotal = this.data.structure.avgFunctionLength * this.data.structure.totalFunctions;
        this.data.structure.totalFunctions += totalFuncs;
        this.data.structure.avgFunctionLength = this.data.structure.totalFunctions > 0
            ? Math.round((prevTotal + avgLen * totalFuncs) / this.data.structure.totalFunctions) : avgLen;
        const srFunctions = totalFuncs > 0 && avgLen <= 25 ? 1 : 0;
        this.data.structure.singleResponsibility = Math.round((this.data.structure.singleResponsibility * (this.data.structure.totalFunctions - totalFuncs) + (srFunctions * totalFuncs)) / this.data.structure.totalFunctions * 100);
        return totalFuncs;
    }
    // ─── Summary ────────────────────────────────────────
    getSummary() {
        const lines = [];
        if (this.data.functionNaming.getter + this.data.functionNaming.handler + this.data.functionNaming.other === 0)
            return [];
        const total = Object.values(this.data.functionNaming).reduce((a, b) => a + (typeof b === 'number' ? b : 0), 0);
        if (total > 0) {
            const top = this.data.functionNaming.topPatterns.slice(0, 2).join(', ');
            lines.push(`Function naming: ${top} (${Object.entries(this.data.functionNaming).filter(([k]) => k !== 'topPatterns').sort((a, b) => b[1] - a[1]).slice(0, 3).map(([k, v]) => `${k}: ${v}`).join(', ')})`);
        }
        if (this.data.componentNaming.consistency > 0)
            lines.push(`Components: ${this.data.componentNaming.consistency}% PascalCase`);
        if (this.data.constantNaming.preference !== 'unknown')
            lines.push(`Constants: ${this.data.constantNaming.preference} (${this.data.constantNaming.screamingSnake} UPPER, ${this.data.constantNaming.camelCase} camel)`);
        if (this.data.asyncStyle.preference !== 'unknown')
            lines.push(`Async: ${this.data.asyncStyle.preference} (${this.data.asyncStyle.awaitCount} await, ${this.data.asyncStyle.thenCount} .then)`);
        if (this.data.destructuring.usageRate > 0)
            lines.push(`Destructuring: ${this.data.destructuring.usageRate}% of assignments`);
        if (this.data.optionalChaining.chainAccess > 0)
            lines.push(`Optional chaining: ${this.data.optionalChaining.usageRate}% of property access`);
        if (this.data.templateLiterals.preference !== 'unknown')
            lines.push(`Strings: ${this.data.templateLiterals.preference}`);
        if (this.data.semicolons.preference !== 'unknown')
            lines.push(`Semicolons: ${this.data.semicolons.preference} (${this.data.semicolons.consistency}% consistent)`);
        if (this.data.quotes.preference !== 'unknown')
            lines.push(`Quotes: ${this.data.quotes.preference}`);
        if (this.data.trailingCommas.preference !== 'unknown')
            lines.push(`Trailing commas: ${this.data.trailingCommas.preference} (${this.data.trailingCommas.consistency}% consistent)`);
        if (this.data.comments.commentRate > 0)
            lines.push(`Comments: ${this.data.comments.commentRate.toFixed(1)} per function (${this.data.comments.lineComments} line, ${this.data.comments.blockComments} block)`);
        if (this.data.structure.avgFunctionLength > 0)
            lines.push(`Structure: avg ${this.data.structure.avgFunctionLength} lines/func, SRP ~${this.data.structure.singleResponsibility}%`);
        return lines;
    }
}
exports.SyntaxEngine = SyntaxEngine;
//# sourceMappingURL=syntax-engine.js.map