import { __awaiter } from "tslib";
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
// Side-effect import — MUST come before `./chat-driver` so the driver subclasses
// jsdom's EventTarget rather than Node's native one (CustomEvent dispatch then
// works). Mirrors `chat-driver.test.ts`.
import './align-event-globals';
import { ChatDriver } from './chat-driver';
// GENC-1351 §5.7 — driver-level compaction: the atomic, destructive replace.
// A minimal fake registry stands in for a provider, so no network is involved.
const asMsg = (o) => o;
/** A registry whose default provider summarizes via `prompt` (undefined = unsupported). */
function registryWith(prompt) {
    const provider = { prompt, getStatus: () => __awaiter(this, void 0, void 0, function* () { return ({ model: 'test-model' }); }) };
    return { default: () => provider };
}
/** 10 messages alternating user/assistant (user at even indices); last carries usage. */
function tenTurnHistory() {
    return Array.from({ length: 10 }, (_, i) => asMsg(Object.assign({ role: i % 2 === 0 ? 'user' : 'assistant', content: `m${i}`, timestamp: `2026-01-01T00:00:${String(i).padStart(2, '0')}.000Z` }, (i === 9 ? { inputTokens: 1234 } : {}))));
}
const Suite = createLogicSuite('chat-driver-compact');
Suite('compact() destructively replaces older turns with one head summary + metadata', () => __awaiter(void 0, void 0, void 0, function* () {
    var _a, _b, _c;
    const driver = new ChatDriver(registryWith(() => __awaiter(void 0, void 0, void 0, function* () { return 'THE SUMMARY'; })));
    driver.loadHistory(tenTurnHistory());
    const before = driver.getHistory().length;
    const summary = yield driver.compact();
    assert.ok(summary, 'returns the created summary message');
    assert.is(summary.role, 'compacted-summary');
    assert.is(summary.content, 'THE SUMMARY');
    assert.is((_a = summary.compaction) === null || _a === void 0 ? void 0 : _a.tokensBefore, 1234, 'captures pre-compaction input tokens');
    assert.is((_b = summary.compaction) === null || _b === void 0 ? void 0 : _b.model, 'test-model', 'records the summarizing model');
    const after = driver.getHistory();
    assert.ok(after.length < before, 'history shrank (destructive)');
    assert.is(after[0].role, 'compacted-summary', 'summary sits at the head');
    assert.is(after[0].timestamp, '2026-01-01T00:00:00.000Z', 'summary inherits the covered region start → sorts to the head in time-ordered views');
    assert.is((_c = after[0].compaction) === null || _c === void 0 ? void 0 : _c.compactedCount, before - (after.length - 1));
    assert.ok(after.slice(1).every((m) => m.role !== 'compacted-summary'), 'exactly one summary — no marker chain');
}));
Suite('compact() is atomic on failure — no splice, surfaces a "sorry" message', () => __awaiter(void 0, void 0, void 0, function* () {
    const driver = new ChatDriver(registryWith(() => __awaiter(void 0, void 0, void 0, function* () {
        throw new Error('network');
    })));
    const original = tenTurnHistory();
    driver.loadHistory(original);
    const result = yield driver.compact();
    assert.is(result, null, 'returns null on failure');
    const after = driver.getHistory();
    assert.ok(after.every((m) => m.role !== 'compacted-summary'), 'nothing compacted');
    // The covered turns are untouched (atomic); only a brief apology is appended so
    // the user knows it failed (GENC-1351 follow-up — surfaced like a turn error).
    assert.is(after.length, original.length + 1, 'only an apology appended');
    assert.is(after[after.length - 1].role, 'assistant');
    assert.ok(/sorry/i.test(after[after.length - 1].content), 'apology is an agent message');
}));
Suite('compact() rolls a prior summary into a single fresh one', () => __awaiter(void 0, void 0, void 0, function* () {
    const driver = new ChatDriver(registryWith(() => __awaiter(void 0, void 0, void 0, function* () { return 'COMBINED'; })));
    driver.loadHistory([
        asMsg({ role: 'compacted-summary', content: 'old', compaction: { compactedCount: 5 } }),
        ...tenTurnHistory(),
    ]);
    const summary = yield driver.compact();
    assert.ok(summary);
    const after = driver.getHistory();
    assert.is(after.filter((m) => m.role === 'compacted-summary').length, 1, 'still exactly one summary after re-compaction');
    assert.is(after[0].content, 'COMBINED');
}));
Suite('compact() no-ops when there is nothing worth compacting', () => __awaiter(void 0, void 0, void 0, function* () {
    const driver = new ChatDriver(registryWith(() => __awaiter(void 0, void 0, void 0, function* () { return 'unused'; })));
    driver.loadHistory([
        asMsg({ role: 'user', content: 'hi' }),
        asMsg({ role: 'assistant', content: 'yo' }),
    ]);
    assert.is(yield driver.compact(), null);
    assert.is(driver.getHistory().length, 2, 'short history untouched');
}));
Suite('compact() no-ops when the default provider cannot summarize', () => __awaiter(void 0, void 0, void 0, function* () {
    const driver = new ChatDriver(registryWith(undefined));
    driver.loadHistory(tenTurnHistory());
    assert.is(yield driver.compact(), null);
    assert.is(driver.getHistory().length, 10, 'history untouched without prompt support');
}));
Suite("canCompact reflects compact()-would-act, keyed on the driver's own history", () => {
    const rich = new ChatDriver(registryWith(() => __awaiter(void 0, void 0, void 0, function* () { return 'x'; })));
    rich.loadHistory(tenTurnHistory());
    assert.is(rich.canCompact(), true, 'enough history → gate open');
    const thin = new ChatDriver(registryWith(() => __awaiter(void 0, void 0, void 0, function* () { return 'x'; })));
    thin.loadHistory([
        asMsg({ role: 'user', content: 'hi' }),
        asMsg({ role: 'assistant', content: 'yo' }),
    ]);
    assert.is(thin.canCompact(), false, 'too short → gate closed (same source compact() uses)');
});
Suite.run();
