"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.buildJourneyTimeline = buildJourneyTimeline;
exports.buildSkillProgression = buildSkillProgression;
exports.buildContextChains = buildContextChains;
exports.buildGoalTracker = buildGoalTracker;
exports.buildJourneyReport = buildJourneyReport;
exports.saveJourneyReport = saveJourneyReport;
const child_process_1 = require("child_process");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const os = __importStar(require("os"));
function safeExec(cmd, cwd) {
    try {
        return (0, child_process_1.execSync)(cmd, { encoding: 'utf-8', cwd: cwd || os.homedir(), maxBuffer: 10 * 1024 * 1024, timeout: 30000, stdio: ['pipe', 'pipe', 'ignore'] }).trim();
    }
    catch {
        return '';
    }
}
function projectDirs(root) {
    const dirs = [];
    try {
        for (const e of fs.readdirSync(root, { withFileTypes: true })) {
            if (e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules') {
                const full = path.join(root, e.name);
                if (fs.existsSync(path.join(full, 'package.json')) || fs.existsSync(path.join(full, '.git'))) {
                    dirs.push(full);
                }
            }
        }
    }
    catch { }
    return dirs;
}
function buildJourneyTimeline(rootDir) {
    const events = [];
    const projects = projectDirs(rootDir);
    for (const prog of projects) {
        const name = path.basename(prog);
        const pkgPath = path.join(prog, 'package.json');
        if (fs.existsSync(pkgPath)) {
            try {
                const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
                const deps = { ...pkg.dependencies, ...pkg.devDependencies };
                const stat = fs.statSync(pkgPath);
                const created = stat.birthtime.toISOString().split('T')[0];
                events.push({ date: created, type: 'milestone', detail: `Project "${name}" created`, project: name, impact: 'high', evidence: 'package.json creation' });
                for (const [dep, version] of Object.entries(deps)) {
                    const majorLibs = ['react', 'vue', 'express', 'next', 'typescript', 'prisma', 'vite', 'jest', 'python', 'django', 'flask', 'postgresql', 'redis', 'docker', 'graphql', 'socket.io', 'tailwind', 'electron'];
                    if (majorLibs.includes(dep.toLowerCase()) || dep === 'typescript') {
                        events.push({ date: created, type: 'first-use', detail: `First used ${dep} ${version}`, project: name, impact: 'high', evidence: `package.json: ${dep}@${version}` });
                    }
                }
            }
            catch { }
        }
        if (fs.existsSync(path.join(prog, '.git'))) {
            const log = safeExec(`git -C "${prog}" log --format="%ai|%s" --diff-filter=A -50`);
            for (const line of log.split('\n').filter(Boolean)) {
                const parts = line.split('|');
                if (parts.length < 2)
                    continue;
                const date = parts[0].trim().slice(0, 10);
                const msg = parts.slice(1).join('|').trim();
                if (msg.match(/\b(add|init|start|begin|create|setup)\b/i) && msg.length < 80) {
                    const exists = events.some(e => e.date === date && e.detail === msg);
                    if (!exists)
                        events.push({ date, type: 'added', detail: msg, project: name, impact: 'medium', evidence: 'git log' });
                }
            }
            let totalCommits = 0;
            const countOutput = safeExec(`git -C "${prog}" rev-list --count HEAD`);
            totalCommits = parseInt(countOutput) || 0;
            if (totalCommits > 100) {
                events.push({ date: new Date().toISOString().split('T')[0], type: 'milestone', detail: `Reached ${totalCommits} commits in ${name}`, project: name, impact: 'medium', evidence: `git: ${totalCommits} commits` });
            }
        }
    }
    events.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
    const seen = new Set();
    const unique = [];
    for (const e of events) {
        const key = `${e.date}|${e.detail}`;
        if (!seen.has(key)) {
            seen.add(key);
            unique.push(e);
        }
    }
    return unique;
}
function buildSkillProgression(rootDir) {
    const skills = [];
    const langMap = { '.ts': 'TypeScript', '.tsx': 'TypeScript', '.js': 'JavaScript', '.jsx': 'JavaScript', '.mjs': 'JavaScript', '.py': 'Python', '.go': 'Go', '.html': 'HTML', '.htm': 'HTML' };
    const langData = new Map();
    const langExts = new Set(Object.keys(langMap));
    function walk(dir, depth = 0) {
        if (depth > 6)
            return;
        let entries;
        try {
            entries = fs.readdirSync(dir, { withFileTypes: true });
        }
        catch {
            return;
        }
        for (const e of entries) {
            if (e.name === 'node_modules' || e.name.startsWith('.') || e.name === 'dist' || e.name === 'build')
                continue;
            const full = path.join(dir, e.name);
            if (e.isDirectory())
                walk(full, depth + 1);
            else if (e.isFile()) {
                const ext = path.extname(e.name).toLowerCase();
                if (!langExts.has(ext))
                    continue;
                const lang = langMap[ext];
                if (!langData.has(lang))
                    langData.set(lang, { files: 0, lines: 0, bugs: 0, clean: 0, firstDate: '', lastDate: '', projects: new Set() });
                const d = langData.get(lang);
                d.files++;
                try {
                    const content = fs.readFileSync(full, 'utf-8');
                    d.lines += content.split('\n').length;
                    const hasBug = /\b(todo|fixme|hack|bug|workaround)\b/i.test(content);
                    if (hasBug)
                        d.bugs++;
                    else
                        d.clean++;
                    const st = fs.statSync(full);
                    const date = st.birthtime.toISOString().split('T')[0];
                    if (!d.firstDate || date < d.firstDate)
                        d.firstDate = date;
                    if (!d.lastDate || date > d.lastDate)
                        d.lastDate = date;
                    const projectMatch = dir.replace(rootDir, '').split(/[\\/]/).filter(Boolean)[0] || 'unknown';
                    d.projects.add(projectMatch);
                }
                catch { }
            }
        }
    }
    walk(rootDir);
    for (const [lang, data] of langData) {
        const cleanRatio = data.files > 0 ? data.clean / data.files : 0;
        let level = 'beginner';
        if (data.files > 500 && cleanRatio > 0.8)
            level = 'mastered';
        else if (data.files > 100 && cleanRatio > 0.6)
            level = 'proficient';
        else if (data.files > 20)
            level = 'intermediate';
        let growth = { direction: 'stable', monthlyRate: '0 new files/month', comment: 'Maintained at current level' };
        if (data.files > 100)
            growth = { direction: 'improving', monthlyRate: 'Active growth', comment: `Strong — ${data.projects.size} projects using ${lang}` };
        skills.push({ area: lang, startDate: data.firstDate, currentLevel: level, metrics: { projectsUsed: data.projects.size, totalFiles: data.files, totalLines: data.lines, bugsFound: data.bugs, bugsFixed: data.clean, cleanFileRatio: Math.round(cleanRatio * 100) }, growth });
    }
    skills.sort((a, b) => b.metrics.totalFiles - a.metrics.totalFiles);
    return skills;
}
function buildContextChains(rootDir) {
    const chains = [];
    const patterns = new Map();
    const projects = projectDirs(rootDir);
    const featurePatterns = [
        { name: 'Rate Limiting / Auth', deps: ['express-rate-limit', 'rate-limiter-flexible', 'passport', 'jsonwebtoken', 'bcrypt', 'express-session'] },
        { name: 'Database / ORM', deps: ['prisma', 'drizzle', 'sequelize', 'typeorm', 'knex', 'better-sqlite3', 'pg', 'mysql2', 'mongoose'] },
        { name: 'Validation', deps: ['zod', 'yup', 'joi', 'valibot'] },
        { name: 'Testing', deps: ['jest', 'vitest', 'mocha', 'playwright', 'pytest'] },
        { name: 'Real-time / WS', deps: ['socket.io', 'ws', 'centrifugo', '@hocuspocus/provider'] },
        { name: 'AI Integration', deps: ['openai', 'anthropic', '@anthropic-ai/sdk', 'ai', '@ai-sdk/openai'] },
        { name: 'Build / Dev', deps: ['vite', 'webpack', 'esbuild', 'rollup', 'turbo'] },
        { name: 'Logging / Monitoring', deps: ['winston', 'pino', 'sentry', '@sentry/node'] },
    ];
    for (const proj of projects) {
        const pkgPath = path.join(proj, 'package.json');
        if (!fs.existsSync(pkgPath))
            continue;
        try {
            const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
            const deps = { ...pkg.dependencies, ...pkg.devDependencies };
            for (const fp of featurePatterns) {
                const found = fp.deps.filter(d => d in deps);
                if (found.length > 0) {
                    const existing = patterns.get(fp.name);
                    if (existing) {
                        existing.totalCount++;
                        existing.successCount++;
                        existing.reused.push(path.basename(proj));
                    }
                    else {
                        const stat = fs.statSync(pkgPath);
                        patterns.set(fp.name, { date: stat.birthtime.toISOString().split('T')[0], project: path.basename(proj), successCount: 1, totalCount: 1, reused: [] });
                    }
                }
            }
        }
        catch { }
    }
    for (const [name, data] of patterns) {
        if (data.totalCount < 2)
            continue;
        const successRate = data.totalCount > 0 ? data.successCount / data.totalCount : 0;
        let recommendation = '';
        if (successRate >= 0.8)
            recommendation = `You consistently use ${name} well. This is a proven strength.`;
        else
            recommendation = `Consider standardizing your ${name} approach across all projects.`;
        chains.push({ pattern: name, description: `Consistently uses ${name} pattern across ${data.totalCount} projects`, firstUsed: { date: data.date, project: data.project }, reusedIn: data.reused.map(r => ({ date: '', project: r, success: true })), successRate, recommendation });
    }
    chains.sort((a, b) => b.reusedIn.length - a.reusedIn.length);
    return chains;
}
function buildGoalTracker(skills) {
    const goalPath = path.join(os.homedir(), '.fivo', 'cell', 'goals.json');
    let existingGoals = [];
    if (fs.existsSync(goalPath)) {
        try {
            existingGoals = JSON.parse(fs.readFileSync(goalPath, 'utf-8')).goals || [];
        }
        catch { }
    }
    const recommendations = [];
    for (const s of skills) {
        if (s.currentLevel === 'intermediate' || s.currentLevel === 'beginner') {
            recommendations.push(`Level up ${s.area} from ${s.currentLevel} → proficient (${s.metrics.totalFiles} files, ${s.metrics.cleanFileRatio}% clean)`);
        }
    }
    if (skills.length === 0) {
        recommendations.push('Run `cell intelligence` first to build skill data');
    }
    recommendations.push('Track your goals: `cell goal add "learn X"`');
    return { goals: existingGoals, learningPath: [], recommendations };
}
function buildJourneyReport(rootDir) {
    const timeline = buildJourneyTimeline(rootDir);
    const skills = buildSkillProgression(rootDir);
    const chains = buildContextChains(rootDir);
    const goals = buildGoalTracker(skills);
    const projects = projectDirs(rootDir);
    const languages = skills.map(s => s.area);
    let totalCommits = 0;
    for (const p of projects) {
        if (fs.existsSync(path.join(p, '.git'))) {
            const count = safeExec(`git -C "${p}" rev-list --count HEAD`);
            totalCommits += parseInt(count) || 0;
        }
    }
    return { timeline, skills, chains, goals, summary: { totalProjects: projects.length, activeSince: timeline.length > 0 ? timeline[0].date : 'unknown', languagesLearned: languages.length, totalCommits, mostUsedLanguage: skills.length > 0 ? skills[0].area : 'unknown', topSkill: skills.find(s => s.currentLevel === 'mastered' || s.currentLevel === 'proficient')?.area || skills[0]?.area || 'unknown', growthRate: skills.filter(s => s.currentLevel === 'proficient' || s.currentLevel === 'mastered').length > 2 ? 'Strong growth' : 'Growing steadily' }, generatedAt: new Date().toISOString() };
}
function saveJourneyReport(report) {
    const dir = path.join(os.homedir(), '.fivo', 'cell');
    if (!fs.existsSync(dir))
        fs.mkdirSync(dir, { recursive: true });
    const fp = path.join(dir, 'journey.json');
    const prev = fs.existsSync(fp) ? JSON.parse(fs.readFileSync(fp, 'utf-8')) : null;
    const historyDir = path.join(dir, 'memory');
    if (!fs.existsSync(historyDir))
        fs.mkdirSync(historyDir, { recursive: true });
    if (prev) {
        const snapshot = path.join(historyDir, `journey-${prev.generatedAt.slice(0, 10)}.json`);
        try {
            fs.writeFileSync(snapshot, JSON.stringify(prev, null, 2), 'utf-8');
        }
        catch { }
    }
    fs.writeFileSync(fp, JSON.stringify(report, null, 2), 'utf-8');
    const mdPath = path.join(dir, 'journey.md');
    fs.writeFileSync(mdPath, renderJourneyMd(report), 'utf-8');
    return fp;
}
function renderJourneyMd(r) {
    const l = [];
    l.push('# 📅 FIVO Cell — Your Developer Journey');
    l.push('');
    l.push(`> Generated: ${r.generatedAt}`);
    l.push(`> Projects: ${r.summary.totalProjects} | Commits: ${r.summary.totalCommits} | Languages: ${r.summary.languagesLearned}`);
    l.push('');
    l.push('## 🎯 Summary');
    l.push('');
    l.push(`- **Active since:** ${r.summary.activeSince}`);
    l.push(`- **Languages learned:** ${r.summary.languagesLearned}`);
    l.push(`- **Top language:** ${r.summary.mostUsedLanguage}`);
    l.push(`- **Top skill:** ${r.summary.topSkill}`);
    l.push(`- **Growth rate:** ${r.summary.growthRate}`);
    l.push('');
    if (r.timeline.length > 0) {
        l.push('## 📅 Journey Timeline');
        l.push('');
        for (const e of r.timeline.slice(0, 25)) {
            const icon = e.impact === 'high' ? '🔴' : e.impact === 'medium' ? '🟡' : '🟢';
            l.push(`- ${icon} **${e.date}** — ${e.detail} (${e.project})`);
        }
        l.push('');
    }
    if (r.skills.length > 0) {
        l.push('## 📈 Skill Progression');
        l.push('');
        l.push('| Skill | Level | Files | Lines | Clean % | Growth |');
        l.push('|-------|-------|-------|-------|---------|--------|');
        for (const s of r.skills) {
            l.push(`| ${s.area} | ${s.currentLevel} | ${s.metrics.totalFiles} | ${s.metrics.totalLines.toLocaleString()} | ${s.metrics.cleanFileRatio}% | ${s.growth.direction} |`);
        }
        l.push('');
    }
    if (r.chains.length > 0) {
        l.push('## 🔗 Context Chains');
        l.push('');
        for (const c of r.chains.slice(0, 6)) {
            l.push(`### ${c.pattern} (${Math.round(c.successRate * 100)}% success)`);
            l.push(`- **First used:** ${c.firstUsed.project} (${c.firstUsed.date})`);
            l.push(`- **Reused in:** ${c.reusedIn.map(r => r.project).join(', ')}`);
            l.push(`- **Recommendation:** ${c.recommendation}`);
            l.push('');
        }
    }
    if (r.goals.recommendations.length > 0) {
        l.push('## 💡 Recommendations');
        l.push('');
        for (const rec of r.goals.recommendations) {
            l.push(`- ${rec}`);
        }
        l.push('');
    }
    return l.join('\n');
}
//# sourceMappingURL=journey-memory.js.map