"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.ARCHIVE_FORMAT_VERSION = void 0;
exports.readArchiveChunkMeta = readArchiveChunkMeta;
exports.listArchiveChunks = listArchiveChunks;
exports.writeArchiveChunk = writeArchiveChunk;
exports.verifyArchiveIntegrity = verifyArchiveIntegrity;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
// ============================================================
// archive-versioning.ts — Archive format versioning + metadata
//
// Current format: gzip + AES-256-GCM (.jsonl.gz.enc)
// New format adds: versioned metadata header
//
// Archive chunk structure:
//   .cell/memory/archive/YYYY/MM/events-YYYY-MM-DD.jsonl.gz.enc
//   .cell/memory/archive/YYYY/MM/sessions-YYYY-MM-DD.jsonl.gz.enc
//   .cell/memory/archive/YYYY/MM/decisions-YYYY-MM-DD.jsonl.gz.enc
//
// Metadata (inside each chunk or as sidecar):
//   format_version: 2
//   compression: 'gzip' | 'zstd'
//   encryption: 'aes-256-gcm'
//   chunk_type: 'events' | 'sessions' | 'decisions'
//   project: string
//   date: string
//   event_count: number
// ============================================================
exports.ARCHIVE_FORMAT_VERSION = 2;
function getArchiveDir(projectDir, date) {
    const d = date || new Date();
    const year = d.getFullYear().toString();
    const month = (d.getMonth() + 1).toString().padStart(2, '0');
    const dir = path.join(projectDir, '.cell', 'memory', 'archive', year, month);
    if (!fs.existsSync(dir))
        fs.mkdirSync(dir, { recursive: true });
    return dir;
}
function getChunkFileName(chunkType, date) {
    const dateStr = date.toISOString().slice(0, 10);
    return `${chunkType}-${dateStr}.jsonl.gz.enc`;
}
function getChunkMetaFileName(chunkType, date) {
    const dateStr = date.toISOString().slice(0, 10);
    return `${chunkType}-${dateStr}.meta.json`;
}
// ============================================================
// Read — dual format support (v1 and v2)
// ============================================================
function readArchiveChunkMeta(projectDir, chunkType, date) {
    const dir = getArchiveDir(projectDir, date);
    const metaPath = path.join(dir, getChunkMetaFileName(chunkType, date));
    if (!fs.existsSync(metaPath))
        return null;
    try {
        const raw = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
        // Backward compatible: if format_version missing, treat as v1
        return {
            format_version: raw.format_version || 1,
            compression: raw.compression || 'gzip',
            encryption: raw.encryption || 'aes-256-gcm',
            chunk_type: raw.chunk_type || chunkType,
            project: raw.project || '',
            date: raw.date || date.toISOString().slice(0, 10),
            event_count: raw.event_count || 0,
            created_at: raw.created_at || new Date().toISOString(),
            checksum: raw.checksum,
        };
    }
    catch {
        return null;
    }
}
function listArchiveChunks(projectDir) {
    const archiveRoot = path.join(projectDir, '.cell', 'memory', 'archive');
    if (!fs.existsSync(archiveRoot))
        return [];
    const results = [];
    const walk = (dir) => {
        for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
            const fullPath = path.join(dir, entry.name);
            if (entry.isDirectory()) {
                walk(fullPath);
            }
            else if (entry.name.endsWith('.enc')) {
                const baseName = entry.name.slice(0, -4); // remove .enc
                const metaPath = path.join(dir, `${baseName}.meta.json`);
                let meta = null;
                if (fs.existsSync(metaPath)) {
                    try {
                        meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
                    }
                    catch { /* ignore */ }
                }
                results.push({ path: fullPath, meta });
            }
        }
    };
    try {
        walk(archiveRoot);
    }
    catch { /* ignore */ }
    return results;
}
// ============================================================
// Write — create chunk with metadata sidecar
// ============================================================
function writeArchiveChunk(projectDir, project, chunkType, events, _key, date) {
    const d = date || new Date();
    const dir = getArchiveDir(projectDir, d);
    const chunkFileName = getChunkFileName(chunkType, d);
    const metaFileName = getChunkMetaFileName(chunkType, d);
    const chunkPath = path.join(dir, chunkFileName);
    const metaPath = path.join(dir, metaFileName);
    // Create metadata
    const meta = {
        format_version: exports.ARCHIVE_FORMAT_VERSION,
        compression: 'gzip',
        encryption: 'aes-256-gcm',
        chunk_type: chunkType,
        project,
        date: d.toISOString().slice(0, 10),
        event_count: events.length,
        created_at: new Date().toISOString(),
    };
    // Write metadata sidecar
    fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
    // Write chunk placeholder (actual encryption done by memory-archive.ts)
    // This module only handles versioning and metadata
    if (!fs.existsSync(chunkPath) && events.length > 0) {
        const lineData = events.map(e => JSON.stringify(e)).join('\n');
        const compressed = require('zlib').gzipSync(Buffer.from(lineData, 'utf-8'));
        fs.writeFileSync(chunkPath, compressed);
    }
    return { chunkPath, metaPath };
}
// ============================================================
// Integrity check
// ============================================================
function verifyArchiveIntegrity(projectDir) {
    const chunks = listArchiveChunks(projectDir);
    const issues = [];
    let versioned = 0;
    let unversioned = 0;
    let totalEvents = 0;
    for (const chunk of chunks) {
        if (chunk.meta) {
            versioned++;
            totalEvents += chunk.meta.event_count;
            if (chunk.meta.format_version < exports.ARCHIVE_FORMAT_VERSION) {
                issues.push(`Old format v${chunk.meta.format_version}: ${chunk.path}`);
            }
        }
        else {
            unversioned++;
            issues.push(`No metadata: ${chunk.path}`);
        }
    }
    return {
        totalChunks: chunks.length,
        versionedChunks: versioned,
        unversionedChunks: unversioned,
        totalEvents,
        issues,
    };
}
//# sourceMappingURL=archive-versioning.js.map