/**
 * Tests for Transcript Logger
 */
import { describe, it, expect, beforeEach } from "vitest";
import { TranscriptLogger, createLogger, getLogger, removeLogger, getActiveSessions, } from "./logger.js";
describe("TranscriptLogger", () => {
    let logger;
    beforeEach(() => {
        logger = new TranscriptLogger("test-session");
    });
    describe("constructor", () => {
        it("creates logger with provided session ID", () => {
            expect(logger.getSessionId()).toBe("test-session");
        });
        it("creates logger with generated session ID if not provided", () => {
            const autoLogger = new TranscriptLogger();
            expect(autoLogger.getSessionId()).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
        });
    });
    describe("append", () => {
        it("appends entry to chain", () => {
            logger.append({
                type: "prompt",
                sessionId: "test-session",
                content: "Hello, world!",
            });
            expect(logger.getEntryCount()).toBe(1);
        });
        it("generates sequential IDs", () => {
            logger.logPrompt("First");
            logger.logPrompt("Second");
            logger.logPrompt("Third");
            const entries = logger.getChain();
            expect(entries[0].id).toBe("test-session-00001");
            expect(entries[1].id).toBe("test-session-00002");
            expect(entries[2].id).toBe("test-session-00003");
        });
        it("links entries with previous hash", () => {
            logger.logPrompt("First");
            logger.logPrompt("Second");
            const entries = logger.getChain();
            expect(entries[0].previousHash).toBe("genesis");
            expect(entries[1].previousHash).toBe(entries[0].entryHash);
        });
    });
    describe("log methods", () => {
        it("logPrompt creates prompt entry", () => {
            const entry = logger.logPrompt("User prompt", "claude-3", { key: "value" });
            expect(entry.type).toBe("prompt");
            expect(entry.content).toBe("User prompt");
            expect(entry.modelId).toBe("claude-3");
            expect(entry.metadata).toEqual({ key: "value" });
        });
        it("logToolCall creates tool_call entry", () => {
            const entry = logger.logToolCall("search", '{"query": "test"}');
            expect(entry.type).toBe("tool_call");
            expect(entry.toolName).toBe("search");
            expect(entry.content).toBe('{"query": "test"}');
        });
        it("logToolResult creates tool_result entry", () => {
            const entry = logger.logToolResult("search", "Results found");
            expect(entry.type).toBe("tool_result");
            expect(entry.toolName).toBe("search");
        });
        it("logModelResponse creates model_response entry", () => {
            const entry = logger.logModelResponse("AI response", "claude-3");
            expect(entry.type).toBe("model_response");
            expect(entry.modelId).toBe("claude-3");
        });
        it("logSystem creates system entry", () => {
            const entry = logger.logSystem("System event");
            expect(entry.type).toBe("system");
        });
        it("logError creates error entry", () => {
            const entry = logger.logError("Something went wrong");
            expect(entry.type).toBe("error");
        });
        it("logRedaction creates redaction entry and sets hasRedactions", () => {
            const entry = logger.logRedaction("abc123hash", "email");
            expect(entry.type).toBe("redaction");
            expect(entry.metadata?.redactionType).toBe("email");
            const transcript = logger.generateSignedTranscript();
            expect(transcript.hasRedactions).toBe(true);
        });
    });
    describe("verify", () => {
        it("returns valid for empty transcript", () => {
            const result = logger.verify();
            expect(result.valid).toBe(true);
            expect(result.entriesVerified).toBe(0);
        });
        it("returns valid for correctly linked chain", () => {
            logger.logPrompt("First");
            logger.logToolCall("tool", "input");
            logger.logToolResult("tool", "output");
            logger.logModelResponse("Response");
            const result = logger.verify();
            expect(result.valid).toBe(true);
            expect(result.entriesVerified).toBe(4);
        });
        it("detects tampering in entry hash", () => {
            logger.logPrompt("Original content");
            // Tamper with the entry hash
            const entries = logger.getChain();
            entries[0].entryHash = "tampered-hash-value";
            const result = logger.verify();
            expect(result.valid).toBe(false);
            expect(result.brokenAt).toBe(0);
            expect(result.issue).toContain("hash mismatch");
        });
        it("detects tampering in content hash", () => {
            logger.logPrompt("Original content");
            // Tamper with the content hash
            const entries = logger.getChain();
            entries[0].contentHash = "tampered-content-hash";
            const result = logger.verify();
            expect(result.valid).toBe(false);
            expect(result.brokenAt).toBe(0);
        });
    });
    describe("generateSignedTranscript", () => {
        it("generates correct entry summary", () => {
            logger.logPrompt("P1");
            logger.logPrompt("P2");
            logger.logToolCall("t", "i");
            logger.logToolResult("t", "o");
            logger.logModelResponse("R");
            const transcript = logger.generateSignedTranscript();
            expect(transcript.entrySummary.prompt).toBe(2);
            expect(transcript.entrySummary.tool_call).toBe(1);
            expect(transcript.entrySummary.tool_result).toBe(1);
            expect(transcript.entrySummary.model_response).toBe(1);
            expect(transcript.entryCount).toBe(5);
        });
        it("includes correct hashes", () => {
            logger.logPrompt("First");
            logger.logPrompt("Last");
            const transcript = logger.generateSignedTranscript();
            const entries = logger.getChain();
            expect(transcript.rootHash).toBe(entries[0].entryHash);
            expect(transcript.tipHash).toBe(entries[1].entryHash);
        });
        it("sets hasRedactions correctly", () => {
            logger.logPrompt("Normal content");
            let transcript = logger.generateSignedTranscript();
            expect(transcript.hasRedactions).toBe(false);
            logger.logRedaction("hash", "ssn");
            transcript = logger.generateSignedTranscript();
            expect(transcript.hasRedactions).toBe(true);
        });
    });
    describe("export methods", () => {
        it("toJSONL returns newline-delimited JSON", () => {
            logger.logPrompt("First");
            logger.logPrompt("Second");
            const jsonl = logger.toJSONL();
            const lines = jsonl.split("\n");
            expect(lines.length).toBe(2);
            expect(JSON.parse(lines[0]).content).toBe("First");
            expect(JSON.parse(lines[1]).content).toBe("Second");
        });
        it("toJSON returns pretty-printed JSON array", () => {
            logger.logPrompt("Test");
            const json = logger.toJSON();
            const parsed = JSON.parse(json);
            expect(Array.isArray(parsed)).toBe(true);
            expect(parsed.length).toBe(1);
        });
    });
});
describe("Logger Factory Functions", () => {
    beforeEach(() => {
        // Clear all active loggers
        for (const sessionId of getActiveSessions()) {
            removeLogger(sessionId);
        }
    });
    describe("createLogger", () => {
        it("creates and registers logger", () => {
            const logger = createLogger("factory-test");
            expect(logger.getSessionId()).toBe("factory-test");
            expect(getActiveSessions()).toContain("factory-test");
        });
        it("generates session ID if not provided", () => {
            const logger = createLogger();
            expect(getActiveSessions()).toContain(logger.getSessionId());
        });
    });
    describe("getLogger", () => {
        it("retrieves existing logger", () => {
            const original = createLogger("get-test");
            original.logPrompt("Test entry");
            const retrieved = getLogger("get-test");
            expect(retrieved).toBe(original);
            expect(retrieved?.getEntryCount()).toBe(1);
        });
        it("returns undefined for non-existent logger", () => {
            const result = getLogger("non-existent");
            expect(result).toBeUndefined();
        });
    });
    describe("removeLogger", () => {
        it("removes logger from registry", () => {
            createLogger("remove-test");
            expect(getActiveSessions()).toContain("remove-test");
            const result = removeLogger("remove-test");
            expect(result).toBe(true);
            expect(getActiveSessions()).not.toContain("remove-test");
        });
        it("returns false for non-existent logger", () => {
            const result = removeLogger("non-existent");
            expect(result).toBe(false);
        });
    });
    describe("getActiveSessions", () => {
        it("returns all active session IDs", () => {
            createLogger("session-1");
            createLogger("session-2");
            createLogger("session-3");
            const sessions = getActiveSessions();
            expect(sessions).toContain("session-1");
            expect(sessions).toContain("session-2");
            expect(sessions).toContain("session-3");
        });
    });
});
//# sourceMappingURL=logger.test.js.map