import { describe, it, expect } from "vitest";
import { extractDatedStatements } from "../timeline-extractor.js";
describe("extractDatedStatements", () => {
    it("returns [] for nullish or empty body", () => {
        expect(extractDatedStatements(null)).toEqual([]);
        expect(extractDatedStatements(undefined)).toEqual([]);
        expect(extractDatedStatements("")).toEqual([]);
    });
    it("returns [] for body with no parseable dates", () => {
        expect(extractDatedStatements("Quiet operator. No major notes.")).toEqual([]);
    });
    it("parses ISO YYYY-MM-DD to day precision", () => {
        const out = extractDatedStatements("Met 2026-03-10 at the AGM.");
        expect(out).toHaveLength(1);
        expect(out[0].occurredAt).toBe("2026-03-10T00:00:00Z");
        expect(out[0].summary).toBe("Met 2026-03-10 at the AGM.");
        expect(out[0].matched).toBe("2026-03-10");
    });
    it("parses day-month-year forms (10 March 2026 / 10 Mar 2026)", () => {
        const long = extractDatedStatements("Workshop on 10 March 2026 went well.");
        expect(long[0].occurredAt).toBe("2026-03-10T00:00:00Z");
        const short = extractDatedStatements("Workshop on 10 Mar 2026 went well.");
        expect(short[0].occurredAt).toBe("2026-03-10T00:00:00Z");
    });
    it("parses month-year to month precision", () => {
        const out = extractDatedStatements("Started consulting in March 2026.");
        expect(out[0].occurredAt).toBe("2026-03-01T00:00:00Z");
    });
    it("parses 'in YYYY' and 'since YYYY' to year precision", () => {
        expect(extractDatedStatements("Founded Rubytech in 2018.")[0].occurredAt).toBe("2018-01-01T00:00:00Z");
        expect(extractDatedStatements("Lives in London since 2020.")[0].occurredAt).toBe("2020-01-01T00:00:00Z");
    });
    it("parses bare year (1900-2099) at word boundaries", () => {
        const out = extractDatedStatements("Joined 2015 cohort.");
        expect(out[0].occurredAt).toBe("2015-01-01T00:00:00Z");
    });
    it("rejects bare year out of plausibility window", () => {
        expect(extractDatedStatements("Year 1800 ledger entry.")).toEqual([]);
        expect(extractDatedStatements("Far-future year 3001 prediction.")).toEqual([]);
    });
    it("does not match prices or times as bare year", () => {
        expect(extractDatedStatements("Paid $2024 for consulting.")).toEqual([]);
        expect(extractDatedStatements("Meeting at 10:2026 (typo).")).toEqual([]);
    });
    it("returns one row per sentence with a date", () => {
        const out = extractDatedStatements("Adam Langley. Met 2026-03-10 at Rubytech AGM. Founded Rubytech in 2018.");
        expect(out).toHaveLength(2);
        expect(out[0].occurredAt).toBe("2026-03-10T00:00:00Z");
        expect(out[1].occurredAt).toBe("2018-01-01T00:00:00Z");
    });
    it("clamps summary to 500 chars at sentence boundaries when possible", () => {
        const longSentence = "On 2026-03-10 " + "lorem ipsum dolor sit amet. ".repeat(40);
        const out = extractDatedStatements(longSentence);
        expect(out).toHaveLength(1);
        expect(out[0].summary.length).toBeLessThanOrEqual(500);
    });
    it("ISO date wins when multiple date forms appear in one sentence", () => {
        const out = extractDatedStatements("Logged 2026-03-10, recorded in 2025.");
        expect(out[0].occurredAt).toBe("2026-03-10T00:00:00Z");
    });
    it("returns no row for malformed ISO dates (no fallback to bare year)", () => {
        // 2026-13-01 fails validMonth. The bare-year regex refuses to match
        // a year that is followed by `-N` (which would mean it is part of a
        // longer date pattern that just failed). Refusal is the correct
        // doctrine: no catch-all collapse.
        const out = extractDatedStatements("Off-record on 2026-13-01.");
        expect(out).toEqual([]);
    });
    // Task 390 — relative + quarter forms via parseRelativeDate.
    describe("relative + quarter forms", () => {
        const REF = new Date("2026-05-20T14:30:00Z"); // Wednesday.
        it("parses 'last Tuesday' against reference", () => {
            const out = extractDatedStatements("Met them last Tuesday.", REF);
            expect(out).toHaveLength(1);
            expect(out[0].occurredAt).toBe("2026-05-19T00:00:00Z");
            expect(out[0].form).toBe("relative");
        });
        it("parses 'two weeks ago' against reference", () => {
            const out = extractDatedStatements("Closed the deal two weeks ago.", REF);
            expect(out[0].occurredAt).toBe("2026-05-06T00:00:00Z");
            expect(out[0].form).toBe("relative");
        });
        it("parses fiscal quarter Q3 2024", () => {
            const out = extractDatedStatements("Revenue dipped in Q3 2024.", REF);
            expect(out[0].occurredAt).toBe("2024-07-01T00:00:00Z");
            expect(out[0].form).toBe("quarter");
        });
        it("parses 'Q1 last year' against reference year", () => {
            const out = extractDatedStatements("Hired the team in Q1 last year.", REF);
            expect(out[0].occurredAt).toBe("2025-01-01T00:00:00Z");
            expect(out[0].form).toBe("quarter");
        });
        it("returns no row for recurring forms", () => {
            const out = extractDatedStatements("We sync every other Friday.", REF);
            expect(out).toEqual([]);
        });
        it("literal forms still take priority over relative", () => {
            const out = extractDatedStatements("On 2026-03-10 we met last Tuesday.", REF);
            expect(out[0].form).toBe("iso");
            expect(out[0].occurredAt).toBe("2026-03-10T00:00:00Z");
        });
        it("defaults reference to now when omitted", () => {
            const out = extractDatedStatements("Met them yesterday.");
            // Just assert that we got a row and the day is recent — exact value
            // depends on the test-run clock.
            expect(out).toHaveLength(1);
            expect(out[0].form).toBe("relative");
        });
    });
});
//# sourceMappingURL=timeline-extractor.test.js.map