"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.syncPatternsToCell = syncPatternsToCell;
exports.syncContextToCell = syncContextToCell;
exports.syncSummariesToCell = syncSummariesToCell;
exports.syncStyleToCell = syncStyleToCell;
exports.syncCellMirror = syncCellMirror;
exports.verifyCellHealth = verifyCellHealth;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const database_1 = require("../database/database");
function ensureDir(dir) {
    if (!fs.existsSync(dir))
        fs.mkdirSync(dir, { recursive: true });
}
function getCellRoot(projectDir) {
    return path.join(projectDir, '.cell');
}
function getMemoryDir(projectDir) {
    return path.join(getCellRoot(projectDir), 'memory');
}
function getSummariesDir(projectDir, period) {
    const dir = path.join(getMemoryDir(projectDir), 'summaries', period);
    ensureDir(dir);
    return dir;
}
function getPatternsDir(projectDir) {
    const dir = path.join(getMemoryDir(projectDir), 'patterns');
    ensureDir(dir);
    return dir;
}
function getStyleDir(projectDir) {
    const dir = path.join(getMemoryDir(projectDir), 'style');
    ensureDir(dir);
    return dir;
}
function getContextDir(projectDir) {
    const dir = path.join(getMemoryDir(projectDir), 'context');
    ensureDir(dir);
    return dir;
}
function writeJson(filePath, data) {
    ensureDir(path.dirname(filePath));
    fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
}
function readJsonSafe(filePath) {
    if (!fs.existsSync(filePath))
        return null;
    try {
        return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
    }
    catch {
        return null;
    }
}
function syncPatternsToCell(projectDir, project) {
    const db = (0, database_1.getDb)();
    const dir = getPatternsDir(projectDir);
    const rows = db.prepare(`SELECT pattern, category, confidence, importance, created_at, last_seen
     FROM memory_patterns WHERE project = ? ORDER BY importance DESC`).all(project);
    const buckets = {
        code: [],
        error: [],
        fix: [],
        architecture: [],
    };
    for (const row of rows) {
        const entry = {
            pattern: row.pattern,
            category: row.category,
            confidence: row.confidence,
            importance: row.importance,
            source: 'verified',
            last_seen: row.last_seen || row.created_at,
        };
        const cat = row.category.toLowerCase();
        if (cat.includes('error')) {
            buckets.error.push(entry);
        }
        else if (cat.includes('fix')) {
            buckets.fix.push(entry);
        }
        else if (cat.includes('arch') || cat.includes('struct') || cat.includes('design')) {
            buckets.architecture.push(entry);
        }
        else {
            buckets.code.push(entry);
        }
    }
    writeJson(path.join(dir, 'code-patterns.json'), buckets.code);
    writeJson(path.join(dir, 'error-patterns.json'), buckets.error);
    writeJson(path.join(dir, 'fix-patterns.json'), buckets.fix);
    writeJson(path.join(dir, 'architecture-patterns.json'), buckets.architecture);
}
// ============================================================
// Context Mirror — writes .cell/memory/context/*.md
// ============================================================
function syncContextToCell(projectDir, project) {
    const db = (0, database_1.getDb)();
    const dir = getContextDir(projectDir);
    // 1. short.md — top 10 recent important events
    const recentImportant = db.prepare(`SELECT type, summary, topic, importance, created_at FROM memory_events
     WHERE project = ? ORDER BY importance DESC, created_at DESC LIMIT 10`).all(project);
    let shortMd = '# Short Context\n\n';
    shortMd += `_Generated: ${new Date().toISOString().slice(0, 16)}_\n\n`;
    for (const ev of recentImportant) {
        const topicTag = ev.topic ? ` [${ev.topic}]` : '';
        shortMd += `- **[${ev.type}]** (imp:${ev.importance}) ${ev.summary}${topicTag}\n`;
    }
    fs.writeFileSync(path.join(dir, 'short.md'), shortMd);
    // 2. last-session.md — events from most recent session
    const lastSession = db.prepare(`SELECT id, start_time, end_time FROM sessions WHERE project = ? ORDER BY id DESC LIMIT 1`).get(project);
    let lastSessionMd = '# Last Session\n\n';
    if (lastSession) {
        const sessionEvents = db.prepare(`SELECT type, summary, topic, importance FROM memory_events
       WHERE project = ? AND created_at >= ? AND created_at <= ?
       ORDER BY importance DESC`).all(project, lastSession.start_time, lastSession.end_time || new Date().toISOString());
        lastSessionMd += `_Session #${lastSession.id}: ${lastSession.start_time} — ${lastSession.end_time || 'active'}_\n\n`;
        lastSessionMd += `**${sessionEvents.length} events**\n\n`;
        for (const ev of sessionEvents.slice(0, 30)) {
            const topicTag = ev.topic ? ` [${ev.topic}]` : '';
            lastSessionMd += `- [${ev.type}] (imp:${ev.importance}) ${ev.summary}${topicTag}\n`;
        }
    }
    else {
        lastSessionMd += 'No sessions recorded yet.\n';
    }
    fs.writeFileSync(path.join(dir, 'last-session.md'), lastSessionMd);
    // 3. branch-*.md — top recent events per branch
    const branches = db.prepare(`SELECT DISTINCT branch FROM memory_events WHERE project = ? AND branch IS NOT NULL AND branch != ''`).all(project);
    for (const { branch } of branches) {
        const branchEvents = db.prepare(`SELECT type, summary, topic, importance, created_at FROM memory_events
       WHERE project = ? AND branch = ?
       ORDER BY importance DESC, created_at DESC LIMIT 20`).all(project, branch);
        let branchMd = `# Branch: ${branch}\n\n`;
        branchMd += `_Updated: ${new Date().toISOString().slice(0, 16)} | ${branchEvents.length} events_\n\n`;
        for (const ev of branchEvents) {
            const topicTag = ev.topic ? ` [${ev.topic}]` : '';
            branchMd += `- [${ev.type}] (imp:${ev.importance}) ${ev.summary}${topicTag}\n`;
        }
        fs.writeFileSync(path.join(dir, `branch-${branch}.md`), branchMd);
    }
    // 4. full.md — comprehensive context (recent + decisions + errors + fixes)
    const recentDecisions = db.prepare(`SELECT summary, topic, importance, created_at FROM memory_events
     WHERE project = ? AND type = 'decision'
     ORDER BY importance DESC, created_at DESC LIMIT 10`).all(project);
    const recentErrors = db.prepare(`SELECT summary, topic, importance, created_at FROM memory_events
     WHERE project = ? AND type = 'error'
     ORDER BY importance DESC, created_at DESC LIMIT 10`).all(project);
    const recentFixes = db.prepare(`SELECT summary, topic, importance, created_at FROM memory_events
     WHERE project = ? AND type = 'fix'
     ORDER BY importance DESC, created_at DESC LIMIT 10`).all(project);
    const recentPatterns = db.prepare(`SELECT pattern, category, importance FROM memory_patterns
     WHERE project = ? ORDER BY importance DESC LIMIT 10`).all(project);
    let fullMd = '# Full Context\n\n';
    fullMd += `_Generated: ${new Date().toISOString().slice(0, 16)}_\n\n`;
    if (recentDecisions.length > 0) {
        fullMd += '## Key Decisions\n\n';
        for (const d of recentDecisions) {
            fullMd += `- (imp:${d.importance}) ${d.summary}\n`;
        }
        fullMd += '\n';
    }
    if (recentErrors.length > 0) {
        fullMd += '## Recent Errors\n\n';
        for (const e of recentErrors) {
            fullMd += `- (imp:${e.importance}) ${e.summary}\n`;
        }
        fullMd += '\n';
    }
    if (recentFixes.length > 0) {
        fullMd += '## Recent Fixes\n\n';
        for (const f of recentFixes) {
            fullMd += `- (imp:${f.importance}) ${f.summary}\n`;
        }
        fullMd += '\n';
    }
    if (recentPatterns.length > 0) {
        fullMd += '## Patterns\n\n';
        for (const p of recentPatterns) {
            fullMd += `- [${p.category}] ${p.pattern}\n`;
        }
        fullMd += '\n';
    }
    if (recentImportant.length > 0) {
        fullMd += '## Top Events (by importance)\n\n';
        for (const ev of recentImportant) {
            fullMd += `- [${ev.type}] (imp:${ev.importance}) ${ev.summary}\n`;
        }
    }
    fs.writeFileSync(path.join(dir, 'full.md'), fullMd);
}
// ============================================================
// Summaries Mirror — writes .cell/memory/summaries/period/*.json
// ============================================================
function syncSummariesToCell(projectDir, project) {
    const db = (0, database_1.getDb)();
    // Daily summaries (last 30 days)
    const dailyRows = db.prepare(`SELECT * FROM memory_summaries WHERE project = ? AND period = 'daily'
     ORDER BY date DESC LIMIT 30`).all(project);
    for (const row of dailyRows) {
        const date = String(row.date || '').slice(0, 10);
        if (date) {
            writeJson(path.join(getSummariesDir(projectDir, 'daily'), `${date}.json`), row);
        }
    }
    // Weekly summaries (last 12 weeks)
    const weeklyRows = db.prepare(`SELECT * FROM memory_summaries WHERE project = ? AND period = 'weekly'
     ORDER BY date DESC LIMIT 12`).all(project);
    for (const row of weeklyRows) {
        const date = String(row.date || '').slice(0, 10);
        if (date) {
            writeJson(path.join(getSummariesDir(projectDir, 'weekly'), `${date}.json`), row);
        }
    }
    // Monthly summaries (last 12 months)
    const monthlyRows = db.prepare(`SELECT * FROM memory_summaries WHERE project = ? AND period = 'monthly'
     ORDER BY date DESC LIMIT 12`).all(project);
    for (const row of monthlyRows) {
        const date = String(row.date || '').slice(0, 7);
        if (date) {
            writeJson(path.join(getSummariesDir(projectDir, 'monthly'), `${date}.json`), row);
        }
    }
}
// ============================================================
// Style Mirror — writes .cell/memory/style/*.json + communication.md
// ============================================================
function syncStyleToCell(projectDir, project) {
    const db = (0, database_1.getDb)();
    const dir = getStyleDir(projectDir);
    // Developer style profile
    const devStyle = db.prepare(`SELECT * FROM style_profiles WHERE project = ? AND type = 'developer' LIMIT 1`).get(project);
    if (devStyle) {
        writeJson(path.join(dir, 'developer-style.json'), devStyle);
    }
    // Project style profile
    const projStyle = db.prepare(`SELECT * FROM style_profiles WHERE project = ? AND type = 'project' LIMIT 1`).get(project);
    if (projStyle) {
        writeJson(path.join(dir, 'project-style.json'), projStyle);
    }
    // Communication style (from style_profiles or generate default)
    const commStyle = db.prepare(`SELECT * FROM style_profiles WHERE project = ? AND type = 'communication' LIMIT 1`).get(project);
    if (commStyle) {
        let commMd = '# Communication Style\n\n';
        commMd += `_Updated: ${new Date().toISOString().slice(0, 16)}_\n\n`;
        const prefs = commStyle.preferences;
        if (prefs) {
            for (const [key, value] of Object.entries(prefs)) {
                commMd += `- **${key}**: ${value}\n`;
            }
        }
        fs.writeFileSync(path.join(dir, 'communication.md'), commMd);
    }
}
// ============================================================
// Master mirror sync — call after any significant DB write
// ============================================================
function syncCellMirror(projectDir, project) {
    // Ensure base dirs exist
    const dirs = [
        getCellRoot(projectDir),
        getMemoryDir(projectDir),
        path.join(getMemoryDir(projectDir), 'summaries'),
        path.join(getMemoryDir(projectDir), 'summaries', 'daily'),
        path.join(getMemoryDir(projectDir), 'summaries', 'weekly'),
        path.join(getMemoryDir(projectDir), 'summaries', 'monthly'),
        path.join(getMemoryDir(projectDir), 'patterns'),
        path.join(getMemoryDir(projectDir), 'style'),
        path.join(getMemoryDir(projectDir), 'context'),
        path.join(getMemoryDir(projectDir), 'archive'),
        path.join(getCellRoot(projectDir), 'private'),
    ];
    for (const d of dirs)
        ensureDir(d);
    // Sync each layer
    try {
        syncPatternsToCell(projectDir, project);
    }
    catch { /* non-critical */ }
    try {
        syncContextToCell(projectDir, project);
    }
    catch { /* non-critical */ }
    try {
        syncSummariesToCell(projectDir, project);
    }
    catch { /* non-critical */ }
    try {
        syncStyleToCell(projectDir, project);
    }
    catch { /* non-critical */ }
}
function verifyCellHealth(projectDir) {
    const cellRoot = getCellRoot(projectDir);
    const memDir = getMemoryDir(projectDir);
    const issues = [];
    const warnings = [];
    function exists(p) { return fs.existsSync(p); }
    // Check if .cell directory exists at all
    const cellExists = exists(cellRoot);
    // Check if database has any data for this project
    let hasData = false;
    try {
        const db = (0, database_1.getDb)();
        const project = path.basename(projectDir);
        const count = db.prepare('SELECT COUNT(*) as c FROM memory_events WHERE project = ?').get(project);
        hasData = count.c > 0;
    }
    catch { /* ignore */ }
    // Critical checks — these indicate actual problems
    function criticalCheck(p, label) {
        const ok = exists(p);
        if (!ok)
            issues.push(`Missing: ${label}`);
        return ok;
    }
    // Optional checks — these are expected to be missing on fresh projects
    function optionalCheck(p, label) {
        const ok = exists(p);
        if (!ok && hasData)
            warnings.push(`Not yet generated: ${label} (will appear after more usage)`);
        return ok;
    }
    const health = {
        // Critical: .cell structure must exist
        handoffCurrent: cellExists ? criticalCheck(path.join(cellRoot, 'handoff', 'current.md'), 'handoff/current.md') : false,
        handoffHistory: cellExists ? exists(path.join(cellRoot, 'handoff', 'history')) : false,
        // Optional: these depend on data accumulation
        summariesDaily: optionalCheck(path.join(memDir, 'summaries', 'daily'), 'memory/summaries/daily/'),
        summariesWeekly: optionalCheck(path.join(memDir, 'summaries', 'weekly'), 'memory/summaries/weekly/'),
        summariesMonthly: optionalCheck(path.join(memDir, 'summaries', 'monthly'), 'memory/summaries/monthly/'),
        // Patterns — check if any exist
        patternsCode: optionalCheck(path.join(memDir, 'patterns', 'code-patterns.json'), 'memory/patterns/code-patterns.json'),
        patternsError: optionalCheck(path.join(memDir, 'patterns', 'error-patterns.json'), 'memory/patterns/error-patterns.json'),
        patternsFix: optionalCheck(path.join(memDir, 'patterns', 'fix-patterns.json'), 'memory/patterns/fix-patterns.json'),
        patternsArch: optionalCheck(path.join(memDir, 'patterns', 'architecture-patterns.json'), 'memory/patterns/architecture-patterns.json'),
        // Style — check if generated
        styleDeveloper: optionalCheck(path.join(memDir, 'style', 'developer-style.json'), 'memory/style/developer-style.json'),
        styleProject: optionalCheck(path.join(memDir, 'style', 'project-style.json'), 'memory/style/project-style.json'),
        styleCommunication: optionalCheck(path.join(memDir, 'style', 'communication.md'), 'memory/style/communication.md'),
        // Context — check if generated
        contextShort: optionalCheck(path.join(memDir, 'context', 'short.md'), 'memory/context/short.md'),
        contextFull: optionalCheck(path.join(memDir, 'context', 'full.md'), 'memory/context/full.md'),
        contextLastSession: optionalCheck(path.join(memDir, 'context', 'last-session.md'), 'memory/context/last-session.md'),
        // Archive and private — should exist
        archiveDir: cellExists ? criticalCheck(path.join(memDir, 'archive'), 'memory/archive/') : false,
        privateDir: cellExists ? criticalCheck(path.join(cellRoot, 'private'), 'private/') : false,
        totalFiles: 0,
        issues,
        warnings,
        status: 'healthy',
    };
    // Count total files
    if (cellExists) {
        try {
            const walk = (dir) => {
                let count = 0;
                for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
                    if (entry.isDirectory()) {
                        count += walk(path.join(dir, entry.name));
                    }
                    else {
                        count++;
                    }
                }
                return count;
            };
            health.totalFiles = walk(cellRoot);
        }
        catch { /* ignore */ }
    }
    // Determine overall status
    if (!cellExists) {
        health.status = 'fresh'; // No .cell directory yet — expected for new projects
    }
    else if (issues.length > 0) {
        health.status = 'broken'; // Critical files missing
    }
    else if (warnings.length > 3) {
        health.status = 'degraded'; // Many optional files missing
    }
    else {
        health.status = 'healthy';
    }
    return health;
}
//# sourceMappingURL=cell-mirror.js.map