import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { whatsappTextNormaliser } from "../../lib/conversation-normalisers/whatsapp-text.js";
// ---------------------------------------------------------------------------
// production-shaped grammar grid for the WhatsApp `_chat.txt`
// normaliser. The pre-897 grid asserted a body-grammar throw on every line
// without `Sender: body` shape; that throw codified the Adam Mackay bug
// (vCards, system messages, forwarded blocks, bare-sender lines all triggered
// `parse-error reason=no-sender-body-separator`). The scanner is now
// body-opaque: every byte after the timestamp prefix is preserved verbatim
// and the chat-mode classifier handles all four shapes downstream.
// ---------------------------------------------------------------------------
describe("whatsapp-text normaliser", () => {
    let tmp = "";
    beforeEach(() => {
        tmp = mkdtempSync(join(tmpdir(), "whatsapp-text-test-"));
    });
    afterEach(() => {
        rmSync(tmp, { recursive: true, force: true });
    });
    function writeChat(content) {
        const filePath = join(tmp, "_chat.txt");
        writeFileSync(filePath, content, "utf-8");
        return filePath;
    }
    it("parses a 4-digit-year DD/MM line with body carrying the Sender: prefix verbatim", () => {
        const filePath = writeChat(`[15/04/2024, 09:30:00] Joel: hi adam\n`);
        const result = whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" });
        expect(result.parsedLines).toHaveLength(1);
        expect(result.parsedLines[0].body).toBe("Joel: hi adam");
        expect(result.parsedLines[0].dateSent).toMatch(/^2024-04-15T09:30:00\+0[01]:00$/);
    });
    it("accepts both 2-digit and 4-digit years in the same file", () => {
        const filePath = writeChat(`[15/04/24, 09:30:00] Joel: legacy line\n[15/04/2024, 09:31:00] Joel: modern line\n`);
        const result = whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" });
        expect(result.parsedLines).toHaveLength(2);
        expect(result.parsedLines[0].dateSent.startsWith("2024-")).toBe(true);
        expect(result.parsedLines[1].dateSent.startsWith("2024-")).toBe(true);
    });
    it("strips leading bidi marks (LRM/RLM) without polluting the next message body", () => {
        const filePath = writeChat(`[15/04/2024, 09:30:00] Joel: line one\n‎[15/04/2024, 09:31:00] Adam: line two\n`);
        const result = whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" });
        expect(result.parsedLines).toHaveLength(2);
        expect(result.parsedLines[1].body).toBe("Adam: line two");
    });
    it("bare-sender — line without `Sender: body` shape parses without throw", () => {
        // Pre-897 this threw `parse-error reason=no-sender-body-separator`.
        const filePath = writeChat(`[15/04/2024, 09:30:00] this is malformed\n`);
        const result = whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" });
        expect(result.parsedLines).toHaveLength(1);
        expect(result.parsedLines[0].body).toBe("this is malformed");
    });
    it("vCard — multi-line BEGIN:VCARD block glues onto the preceding match", () => {
        // WhatsApp vCard exports surface as multi-line bodies after a header line.
        const filePath = writeChat(`[15/04/2024, 09:30:00] Joel: ‎contact card\nBEGIN:VCARD\nVERSION:3.0\nFN:Adam Mackay\nTEL:+447700900000\nEND:VCARD\n[15/04/2024, 09:31:00] Joel: next message\n`);
        const result = whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" });
        expect(result.parsedLines).toHaveLength(2);
        expect(result.parsedLines[0].body).toContain("BEGIN:VCARD");
        expect(result.parsedLines[0].body).toContain("FN:Adam Mackay");
        expect(result.parsedLines[1].body).toBe("Joel: next message");
    });
    it("system-message — `Joel created group ...` line parses without throw", () => {
        // Pre-897 this branched into LINE_LEVEL_SYSTEM_PATTERNS and counted
        // systemSkipped++; post-897 the scanner doesn't classify, so this is a
        // regular ParsedLine with the system-message text in body.
        const filePath = writeChat(`[15/04/2024, 09:30:00] Joel created group "Adam"\n[15/04/2024, 09:31:00] Joel: hi\n`);
        const result = whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" });
        expect(result.parsedLines).toHaveLength(2);
        expect(result.parsedLines[0].body).toBe(`Joel created group "Adam"`);
    });
    it("forwarded-block — leading `‎Forwarded\\n[ts] ...` block survives the scanner", () => {
        const filePath = writeChat(`[15/04/2024, 09:30:00] Joel: ‎Forwarded\nrelevant context body line one\nrelevant context body line two\n[15/04/2024, 09:31:00] Adam: thanks\n`);
        const result = whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" });
        expect(result.parsedLines).toHaveLength(2);
        expect(result.parsedLines[0].body).toContain("relevant context body line one");
        expect(result.parsedLines[1].body).toBe("Adam: thanks");
    });
    it("no-timestamp-archive — file with zero matching prefixes returns empty parsedLines (no throw)", () => {
        // This is the document-routing signal: bin sees parsed=0 and routes to
        // document-ingest instead of failing.
        const filePath = writeChat(`Just a paragraph of text.\nNo timestamps anywhere.\nLooks like a memo, not a chat.\n`);
        const result = whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" });
        expect(result.parsedLines).toHaveLength(0);
        expect(result.counters.parsed).toBe(0);
    });
    it("empty-archive — genuinely empty file throws", () => {
        // Empty file is unambiguous: not a chat, not a document. Stay loud.
        const filePath = writeChat("");
        expect(() => whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" })).toThrow(/file is empty/);
    });
    it("counts no skips post-897 (counters.systemSkipped/mediaSkipped are structural zeroes)", () => {
        const filePath = writeChat(`[15/04/2024, 09:30:00] Joel: <Media omitted>\n[15/04/2024, 09:31:00] Joel: real msg\n`);
        const result = whatsappTextNormaliser({ filePath, accountId: "acct-1", timezone: "Europe/London" });
        // <Media omitted> is now a regular body — no skipping at the parser layer.
        expect(result.parsedLines).toHaveLength(2);
        expect(result.counters.mediaSkipped).toBe(0);
        expect(result.counters.systemSkipped).toBe(0);
    });
    it("returns a stable archiveSha256 for identical bytes (cleanup discriminator)", () => {
        const fp = writeChat(`[15/04/2024, 09:30:00] Joel: stable\n`);
        const a = whatsappTextNormaliser({ filePath: fp, accountId: "acct-1", timezone: "Europe/London" });
        const b = whatsappTextNormaliser({ filePath: fp, accountId: "acct-1", timezone: "Europe/London" });
        expect(a.archiveSha256).toBe(b.archiveSha256);
        expect(a.archiveSha256).toMatch(/^[a-f0-9]{64}$/);
    });
});
//# sourceMappingURL=conversation-normalisers-whatsapp-text.test.js.map