"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.loadAutomationConfig = loadAutomationConfig;
exports.saveAutomationConfig = saveAutomationConfig;
exports.initAutomationConfig = initAutomationConfig;
exports.isGitRepo = isGitRepo;
exports.getCurrentBranch = getCurrentBranch;
exports.getLatestCommitHash = getLatestCommitHash;
exports.getCommitsSince = getCommitsSince;
exports.getAllCommits = getAllCommits;
exports.getTopicFromCommit = getTopicFromCommit;
exports.getImportanceForCommit = getImportanceForCommit;
exports.syncGitCommitsToMemory = syncGitCommitsToMemory;
exports.detectFileTopics = detectFileTopics;
exports.getAutomationStatus = getAutomationStatus;
const child_process_1 = require("child_process");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const database_1 = require("../database/database");
const memory_event_store_1 = require("../stores/memory-event-store");
const DEFAULT_CONFIG = {
    autoRecordCommits: true,
    autoRecordTestRuns: true,
    autoRecordErrors: true,
    maxCommitsPerSync: 50,
};
function getConfigPath(projectDir) {
    return path.join(projectDir, '.cell', 'memory', 'automation.json');
}
function loadAutomationConfig(projectDir) {
    const p = getConfigPath(projectDir);
    if (!fs.existsSync(p))
        return null;
    try {
        return JSON.parse(fs.readFileSync(p, 'utf-8'));
    }
    catch {
        return null;
    }
}
function saveAutomationConfig(config) {
    const p = getConfigPath(config.projectDir);
    const dir = path.dirname(p);
    if (!fs.existsSync(dir))
        fs.mkdirSync(dir, { recursive: true });
    fs.writeFileSync(p, JSON.stringify(config, null, 2), 'utf-8');
}
function initAutomationConfig(project, projectDir, overrides) {
    const existing = loadAutomationConfig(projectDir);
    if (existing)
        return existing;
    const config = {
        ...DEFAULT_CONFIG,
        project,
        projectDir,
        ...overrides,
    };
    saveAutomationConfig(config);
    return config;
}
function isGitRepo(projectDir) {
    try {
        (0, child_process_1.execSync)('git rev-parse --is-inside-work-tree', { cwd: projectDir, stdio: 'pipe', timeout: 5000 });
        return true;
    }
    catch {
        return false;
    }
}
function getCurrentBranch(projectDir) {
    try {
        return (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', { cwd: projectDir, stdio: 'pipe', timeout: 5000 }).toString().trim();
    }
    catch {
        return 'unknown';
    }
}
function getLatestCommitHash(projectDir) {
    try {
        return (0, child_process_1.execSync)('git rev-parse HEAD', { cwd: projectDir, stdio: 'pipe', timeout: 5000 }).toString().trim();
    }
    catch {
        return null;
    }
}
function getCommitsSince(projectDir, sinceHash, limit = 50) {
    try {
        const format = '%H|%h|%an|%aI|%s|%b';
        const cmd = `git log --format="${format}" --no-merges ${sinceHash}..HEAD`;
        const output = (0, child_process_1.execSync)(cmd, { cwd: projectDir, stdio: 'pipe', timeout: 10000, maxBuffer: 10 * 1024 * 1024 }).toString().trim();
        if (!output)
            return [];
        const lines = output.split('\n').filter(l => l.trim());
        const commits = [];
        for (const line of lines.slice(0, limit)) {
            const parts = line.split('|');
            if (parts.length < 5)
                continue;
            const hash = parts[0];
            const shortHash = parts[1];
            const author = parts[2];
            const date = parts[3];
            const subject = parts[4];
            const body = parts.slice(5).join('|').trim();
            const files = getCommitFiles(projectDir, hash);
            const stats = getCommitStats(projectDir, hash);
            commits.push({
                hash,
                shortHash,
                author,
                date,
                subject,
                body,
                files,
                branch: getCurrentBranch(projectDir),
                insertions: stats.insertions,
                deletions: stats.deletions,
            });
        }
        return commits;
    }
    catch {
        return [];
    }
}
function getAllCommits(projectDir, limit = 50) {
    try {
        const format = '%H|%h|%an|%aI|%s|%b';
        const cmd = `git log --format="${format}" --no-merges -${limit}`;
        const output = (0, child_process_1.execSync)(cmd, { cwd: projectDir, stdio: 'pipe', timeout: 10000, maxBuffer: 10 * 1024 * 1024 }).toString().trim();
        if (!output)
            return [];
        const lines = output.split('\n').filter(l => l.trim());
        const commits = [];
        for (const line of lines) {
            const parts = line.split('|');
            if (parts.length < 5)
                continue;
            const hash = parts[0];
            const shortHash = parts[1];
            const author = parts[2];
            const date = parts[3];
            const subject = parts[4];
            const body = parts.slice(5).join('|').trim();
            const files = getCommitFiles(projectDir, hash);
            const stats = getCommitStats(projectDir, hash);
            commits.push({
                hash,
                shortHash,
                author,
                date,
                subject,
                body,
                files,
                branch: getCurrentBranch(projectDir),
                insertions: stats.insertions,
                deletions: stats.deletions,
            });
        }
        return commits;
    }
    catch {
        return [];
    }
}
function getCommitFiles(projectDir, hash) {
    try {
        const output = (0, child_process_1.execSync)(`git diff-tree --no-commit-id --name-only -r ${hash}`, {
            cwd: projectDir, stdio: 'pipe', timeout: 5000,
        }).toString().trim();
        return output ? output.split('\n').filter(f => f.trim()) : [];
    }
    catch {
        return [];
    }
}
function getCommitStats(projectDir, hash) {
    try {
        const output = (0, child_process_1.execSync)(`git diff-tree --numstat ${hash}`, {
            cwd: projectDir, stdio: 'pipe', timeout: 5000,
        }).toString().trim();
        let insertions = 0;
        let deletions = 0;
        for (const line of output.split('\n')) {
            const parts = line.split('\t');
            if (parts.length >= 2) {
                const ins = parseInt(parts[0], 10);
                const del = parseInt(parts[1], 10);
                if (!isNaN(ins))
                    insertions += ins;
                if (!isNaN(del))
                    deletions += del;
            }
        }
        return { insertions, deletions };
    }
    catch {
        return { insertions: 0, deletions: 0 };
    }
}
function getTopicFromCommit(commit) {
    const s = commit.subject.toLowerCase();
    if (s.includes('security') || s.includes('vuln'))
        return 'security';
    if (s.includes('fix') || s.includes('bug') || s.includes('patch'))
        return 'bugfix';
    if (s.includes('feat') || s.includes('add') || s.includes('implement'))
        return 'feature';
    if (s.includes('refactor') || s.includes('cleanup') || s.includes('restructure'))
        return 'refactor';
    if (s.includes('test') || s.includes('spec') || s.includes('coverage'))
        return 'testing';
    if (s.includes('doc') || s.includes('readme') || s.includes('comment'))
        return 'documentation';
    if (s.includes('perf') || s.includes('optim') || s.includes('speed'))
        return 'performance';
    if (s.includes('auth'))
        return 'security';
    if (s.includes('config') || s.includes('setup') || s.includes('env'))
        return 'configuration';
    if (s.includes('deploy') || s.includes('release') || s.includes('version'))
        return 'deployment';
    if (s.includes('memory') || s.includes('context'))
        return 'memory-system';
    if (s.includes('mcp') || s.includes('tool'))
        return 'mcp-tools';
    return 'general';
}
function getImportanceForCommit(commit) {
    const topic = getTopicFromCommit(commit);
    const topicImportance = {
        bugfix: 7,
        feature: 6,
        security: 9,
        deployment: 8,
        configuration: 5,
        'memory-system': 8,
        'mcp-tools': 7,
        testing: 5,
        documentation: 3,
        performance: 7,
        refactor: 5,
        general: 4,
    };
    let base = topicImportance[topic] || 4;
    if (commit.files.length > 10)
        base = Math.min(10, base + 1);
    if (commit.insertions + commit.deletions > 500)
        base = Math.min(10, base + 1);
    return base;
}
function syncGitCommitsToMemory(project, projectDir, options) {
    const config = initAutomationConfig(project, projectDir);
    if (!isGitRepo(projectDir))
        return { synced: 0, latestHash: null, commits: [] };
    const sinceHash = options?.sinceHash || config.lastSyncHash || getOldestCommitHash(projectDir);
    const limit = options?.limit || config.maxCommitsPerSync;
    let commits;
    if (sinceHash && isKnownCommit(projectDir, sinceHash)) {
        commits = getCommitsSince(projectDir, sinceHash, limit);
    }
    else {
        commits = getAllCommits(projectDir, limit);
    }
    const branch = getCurrentBranch(projectDir);
    let synced = 0;
    for (const commit of commits) {
        const exists = db.hasCommitRecorded(project, commit.hash);
        if (exists)
            continue;
        (0, memory_event_store_1.recordMemoryEvent)({
            project,
            branch,
            type: 'branch',
            topic: getTopicFromCommit(commit),
            summary: commit.subject,
            details: {
                gitHash: commit.hash,
                gitShortHash: commit.shortHash,
                gitAuthor: commit.author,
                gitDate: commit.date,
                gitBody: commit.body,
                insertions: commit.insertions,
                deletions: commit.deletions,
                source: 'git-automation',
            },
            files: commit.files,
            importance: getImportanceForCommit(commit),
            tool: 'cell-automation',
        });
        synced++;
    }
    const latestHash = getLatestCommitHash(projectDir);
    config.lastSyncHash = latestHash || undefined;
    config.lastSyncAt = new Date().toISOString();
    saveAutomationConfig(config);
    return { synced, latestHash, commits };
}
function getOldestCommitHash(projectDir) {
    try {
        return (0, child_process_1.execSync)('git rev-list --max-parents=0 HEAD', { cwd: projectDir, stdio: 'pipe', timeout: 5000 }).toString().trim().split('\n')[0] || null;
    }
    catch {
        return null;
    }
}
function isKnownCommit(projectDir, hash) {
    try {
        (0, child_process_1.execSync)(`git cat-file -t ${hash}`, { cwd: projectDir, stdio: 'pipe', timeout: 3000 });
        return true;
    }
    catch {
        return false;
    }
}
const db = {
    hasCommitRecorded(project, hash) {
        const d = (0, database_1.getDb)();
        const row = d.prepare(`SELECT id FROM memory_events WHERE project = ? AND details_json LIKE ? AND type = 'branch' LIMIT 1`).get(project, `%${hash}%`);
        return !!row;
    },
};
function detectFileTopics(files) {
    const topics = new Set();
    for (const f of files) {
        const ext = path.extname(f).toLowerCase();
        const basename = path.basename(f).toLowerCase();
        if (ext === '.test.ts' || ext === '.test.js' || ext === '.spec.ts' || basename.includes('.test.'))
            topics.add('testing');
        if (ext === '.md')
            topics.add('documentation');
        if (ext === '.json' && basename.includes('package'))
            topics.add('configuration');
        if (ext === '.json' && basename.includes('tsconfig'))
            topics.add('configuration');
        if (basename.includes('.env') || basename.includes('config'))
            topics.add('configuration');
        if (basename.includes('dockerfile') || basename.includes('docker-compose'))
            topics.add('deployment');
        if (f.includes('security') || f.includes('auth'))
            topics.add('security');
        if (f.includes('memory'))
            topics.add('memory-system');
        if (f.includes('mcp') || f.includes('tool'))
            topics.add('mcp-tools');
        if (f.includes('test') || f.includes('spec'))
            topics.add('testing');
        if (f.includes('.cell'))
            topics.add('cell-config');
    }
    return [...topics];
}
function getAutomationStatus(projectDir) {
    const config = loadAutomationConfig(projectDir);
    return {
        isGitRepo: isGitRepo(projectDir),
        branch: isGitRepo(projectDir) ? getCurrentBranch(projectDir) : 'N/A',
        latestCommit: getLatestCommitHash(projectDir),
        configExists: !!config,
        lastSync: config?.lastSyncAt || null,
    };
}
//# sourceMappingURL=memory-automation.js.map