/**
 * Evidence Store
 *
 * Storage and retrieval for evidence bundles.
 *
 * @module evidence/store
 */
import { readFile, writeFile, mkdir, access, readdir, stat } from "fs/promises";
import { join } from "path";
import { createHash } from "crypto";
import { logger } from "../logger.js";
import { calculateBundleDigest } from "./collector.js";
const EVIDENCE_DIR = ".vaspera/evidence";
/**
 * Ensure evidence directory exists
 */
async function ensureEvidenceDir(projectPath) {
    const evidenceDir = join(projectPath, EVIDENCE_DIR);
    try {
        await access(evidenceDir);
    }
    catch {
        await mkdir(evidenceDir, { recursive: true });
    }
    return evidenceDir;
}
/**
 * Store an evidence bundle
 */
export async function storeEvidenceBundle(projectPath, bundle) {
    const evidenceDir = await ensureEvidenceDir(projectPath);
    const filename = `${bundle.id}.json`;
    const filepath = join(evidenceDir, filename);
    await writeFile(filepath, JSON.stringify(bundle, null, 2), "utf-8");
    logger.info("evidence.store.saved", { bundleId: bundle.id, path: filepath });
    return filepath;
}
/**
 * Load an evidence bundle by ID
 */
export async function loadEvidenceBundle(projectPath, bundleId) {
    const evidenceDir = join(projectPath, EVIDENCE_DIR);
    const filepath = join(evidenceDir, `${bundleId}.json`);
    try {
        await access(filepath);
        const content = await readFile(filepath, "utf-8");
        return JSON.parse(content);
    }
    catch {
        return null;
    }
}
/**
 * List all evidence bundles for a project
 */
export async function listEvidenceBundles(projectPath) {
    const evidenceDir = join(projectPath, EVIDENCE_DIR);
    try {
        await access(evidenceDir);
    }
    catch {
        return [];
    }
    const files = await readdir(evidenceDir);
    const bundles = [];
    for (const file of files) {
        if (!file.endsWith(".json"))
            continue;
        try {
            const content = await readFile(join(evidenceDir, file), "utf-8");
            const bundle = JSON.parse(content);
            bundles.push({
                id: bundle.id,
                createdAt: bundle.createdAt,
                certificationId: bundle.certificationId,
                artifactCount: bundle.artifacts.length,
            });
        }
        catch {
            // Skip invalid files
        }
    }
    // Sort by creation date, newest first
    bundles.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
    return bundles;
}
/**
 * Verify an evidence bundle's integrity
 */
export async function verifyEvidenceBundle(bundle) {
    const result = {
        verified: false,
        bundleId: bundle.id,
        artifactsIntact: true,
        failedArtifacts: [],
        verifiedAt: new Date().toISOString(),
    };
    // Verify bundle digest
    const calculatedDigest = calculateBundleDigest(bundle.artifacts);
    if (calculatedDigest !== bundle.bundleDigest) {
        result.error = `Bundle digest mismatch: expected ${bundle.bundleDigest}, got ${calculatedDigest}`;
        result.artifactsIntact = false;
        return result;
    }
    // Verify each artifact with inline content
    for (const artifact of bundle.artifacts) {
        if (artifact.content) {
            const calculatedHash = createHash("sha256")
                .update(Buffer.from(artifact.content, "utf-8"))
                .digest("hex");
            if (calculatedHash !== artifact.contentDigest) {
                result.artifactsIntact = false;
                result.failedArtifacts.push(artifact.name);
            }
        }
        // Note: For non-inline artifacts, we can't verify without accessing the stored file
    }
    // Verify signature if present
    if (bundle.signature) {
        // Signature verification would call verifyBlob from src/sbom/signing.ts
        // For now, we just check if the signature exists
        result.signatureValid = true;
    }
    result.verified = result.artifactsIntact && result.failedArtifacts.length === 0;
    logger.info("evidence.verify.complete", {
        bundleId: bundle.id,
        verified: result.verified,
        failedCount: result.failedArtifacts.length,
    });
    return result;
}
/**
 * Get evidence bundle statistics
 */
export async function getEvidenceStats(projectPath) {
    const evidenceDir = join(projectPath, EVIDENCE_DIR);
    try {
        await access(evidenceDir);
    }
    catch {
        return { bundleCount: 0, totalSizeBytes: 0 };
    }
    const files = await readdir(evidenceDir);
    const jsonFiles = files.filter((f) => f.endsWith(".json"));
    let totalSize = 0;
    let oldest;
    let newest;
    for (const file of jsonFiles) {
        const filepath = join(evidenceDir, file);
        const stats = await stat(filepath);
        totalSize += stats.size;
        try {
            const content = await readFile(filepath, "utf-8");
            const bundle = JSON.parse(content);
            if (!oldest || bundle.createdAt < oldest) {
                oldest = bundle.createdAt;
            }
            if (!newest || bundle.createdAt > newest) {
                newest = bundle.createdAt;
            }
        }
        catch {
            // Skip invalid files
        }
    }
    return {
        bundleCount: jsonFiles.length,
        totalSizeBytes: totalSize,
        oldestBundle: oldest,
        newestBundle: newest,
    };
}
//# sourceMappingURL=store.js.map