/**
 * Selective File Rollback (Item 109)
 * Roll back individual files from checkpoints
 */
import fs from 'fs-extra';
import path from 'path';
import { EventEmitter } from 'events';
import crypto from 'crypto';
export class SelectiveRollbackManager extends EventEmitter {
    versions = new Map();
    maxVersionsPerFile = 20;
    computeHash(content) {
        return crypto.createHash('sha256').update(content).digest('hex').slice(0, 12);
    }
    saveVersion(filePath, content, source = 'manual') {
        const normalized = path.normalize(filePath);
        const version = {
            id: crypto.randomBytes(6).toString('hex'),
            path: normalized,
            content,
            hash: this.computeHash(content),
            timestamp: new Date(),
            source,
        };
        const fileVersions = this.versions.get(normalized) || [];
        // Skip if content is same as latest
        if (fileVersions.length > 0 && fileVersions[0].hash === version.hash) {
            return fileVersions[0];
        }
        fileVersions.unshift(version);
        // Trim old versions
        if (fileVersions.length > this.maxVersionsPerFile) {
            fileVersions.pop();
        }
        this.versions.set(normalized, fileVersions);
        this.emit('version-saved', version);
        return version;
    }
    getVersions(filePath) {
        return this.versions.get(path.normalize(filePath)) || [];
    }
    getVersion(filePath, versionId) {
        const versions = this.getVersions(filePath);
        return versions.find(v => v.id === versionId);
    }
    async rollbackFile(filePath, versionId) {
        const normalized = path.normalize(filePath);
        const version = this.getVersion(normalized, versionId);
        if (!version) {
            return { success: false, path: normalized, fromVersion: '', toVersion: versionId, error: 'Version not found' };
        }
        try {
            // Save current state before rollback
            if (await fs.pathExists(normalized)) {
                const currentContent = await fs.readFile(normalized, 'utf-8');
                this.saveVersion(normalized, currentContent, 'manual');
            }
            // Perform rollback
            await fs.ensureDir(path.dirname(normalized));
            await fs.writeFile(normalized, version.content, 'utf-8');
            this.emit('file-rolled-back', { path: normalized, versionId });
            return { success: true, path: normalized, fromVersion: 'current', toVersion: versionId };
        }
        catch (error) {
            return { success: false, path: normalized, fromVersion: '', toVersion: versionId, error: String(error) };
        }
    }
    async rollbackMultiple(files) {
        const results = [];
        for (const file of files) {
            results.push(await this.rollbackFile(file.path, file.versionId));
        }
        return results;
    }
    compareVersions(filePath, versionId1, versionId2) {
        const v1 = this.getVersion(filePath, versionId1);
        const v2 = this.getVersion(filePath, versionId2);
        if (!v1 || !v2)
            return null;
        const lines1 = v1.content.split('\n');
        const lines2 = v2.content.split('\n');
        let added = 0, removed = 0, changed = 0;
        const maxLen = Math.max(lines1.length, lines2.length);
        for (let i = 0; i < maxLen; i++) {
            if (i >= lines1.length)
                added++;
            else if (i >= lines2.length)
                removed++;
            else if (lines1[i] !== lines2[i])
                changed++;
        }
        return { added, removed, changed };
    }
    getLatestVersion(filePath) {
        const versions = this.getVersions(filePath);
        return versions[0];
    }
    clearVersions(filePath) {
        this.versions.delete(path.normalize(filePath));
        this.emit('versions-cleared', filePath);
    }
    getAllTrackedFiles() {
        return Array.from(this.versions.keys());
    }
    getStats() {
        let totalVersions = 0;
        for (const versions of this.versions.values()) {
            totalVersions += versions.length;
        }
        return { totalFiles: this.versions.size, totalVersions };
    }
}
let instance = null;
export function getSelectiveRollbackManager() {
    if (!instance)
        instance = new SelectiveRollbackManager();
    return instance;
}
export default SelectiveRollbackManager;
//# sourceMappingURL=selective-rollback.js.map