"use strict";
/**
 * test_cli_inbox — v1.11.0 regression suite.
 *
 * Asserts:
 *   1. enqueue → drain round-trip
 *   2. reply round-trip via writeReply / readReply / waitForReply
 *   3. TTL expiry deletes expired files on next drain
 *   4. acknowledge deletes the message file
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const CliInbox_1 = require("./cli/CliInbox");
function assert(cond, msg) {
    if (!cond)
        throw new Error(`assertion failed: ${msg}`);
}
function mkTmp() {
    return fs.mkdtempSync(path.join(os.tmpdir(), 'cli-inbox-test-'));
}
function rmTmp(dir) {
    try {
        fs.rmSync(dir, { recursive: true, force: true });
    }
    catch { /* ignore */ }
}
async function withHome(home, fn) {
    const prev = process.env.HOME;
    process.env.HOME = home;
    try {
        return await fn();
    }
    finally {
        if (prev === undefined)
            delete process.env.HOME;
        else
            process.env.HOME = prev;
    }
}
async function scenarioRoundTrip() {
    const tmp = mkTmp();
    try {
        await withHome(tmp, async () => {
            const id = CliInbox_1.CliInbox.enqueue({
                ttlSeconds: 60,
                kind: 'command',
                origin: 'telegram',
                verb: 'run',
                args: ['demo'],
            });
            assert(id.length > 0, 'enqueue returns ULID');
            const pending = await CliInbox_1.CliInbox.drain();
            assert(pending.length === 1, `expected 1 pending, got ${pending.length}`);
            assert(pending[0].verb === 'run', 'verb preserved');
            assert(pending[0].id === id, 'id preserved');
        });
        console.log('✅ scenario 1: enqueue → drain round-trip');
    }
    finally {
        rmTmp(tmp);
    }
}
async function scenarioReply() {
    const tmp = mkTmp();
    try {
        await withHome(tmp, async () => {
            const id = CliInbox_1.CliInbox.enqueue({ ttlSeconds: 60, kind: 'command', origin: 'telegram', verb: 'memory', args: ['rafael'] });
            assert(CliInbox_1.CliInbox.readReply(id) === null, 'no reply yet');
            // Simulate core processing in background
            setTimeout(() => {
                CliInbox_1.CliInbox.reply(id, { ok: true, result: 'fact-1', repliedAt: new Date().toISOString() });
            }, 50);
            const reply = await CliInbox_1.CliInbox.waitForReply(id, 2_000, 25);
            assert(reply !== null, 'reply received within timeout');
            assert(reply.ok === true, 'reply ok');
            assert(reply.result === 'fact-1', 'reply result preserved');
        });
        console.log('✅ scenario 2: reply round-trip with waitForReply');
    }
    finally {
        rmTmp(tmp);
    }
}
async function scenarioTtlExpiry() {
    const tmp = mkTmp();
    try {
        await withHome(tmp, async () => {
            // Manually create an already-expired message file
            const { inbox } = CliInbox_1.CliInbox._dirs();
            fs.mkdirSync(inbox, { recursive: true });
            const expired = {
                id: 'EXPIRED01',
                createdAt: new Date(Date.now() - 7200_000).toISOString(), // 2h ago
                ttlSeconds: 60, // 60s TTL → long since expired
                kind: 'notification',
                origin: 'daemon',
                text: 'old',
            };
            fs.writeFileSync(path.join(inbox, `${expired.id}.json`), JSON.stringify(expired));
            const liveId = CliInbox_1.CliInbox.enqueue({ ttlSeconds: 3600, kind: 'notification', origin: 'daemon', text: 'fresh' });
            const pending = await CliInbox_1.CliInbox.drain();
            assert(pending.length === 1, `drain should yield only the live message, got ${pending.length}`);
            assert(pending[0].id === liveId, 'live message survived');
            assert(!fs.existsSync(path.join(inbox, 'EXPIRED01.json')), 'expired file must be deleted');
        });
        console.log('✅ scenario 3: TTL expiry cleans up old messages');
    }
    finally {
        rmTmp(tmp);
    }
}
async function scenarioAck() {
    const tmp = mkTmp();
    try {
        await withHome(tmp, async () => {
            const id = CliInbox_1.CliInbox.enqueue({ ttlSeconds: 60, kind: 'notification', origin: 'daemon', text: 'hi' });
            const { inbox } = CliInbox_1.CliInbox._dirs();
            const file = path.join(inbox, `${id}.json`);
            assert(fs.existsSync(file), 'message file exists pre-ack');
            CliInbox_1.CliInbox.acknowledge(id);
            assert(!fs.existsSync(file), 'message file gone post-ack');
            // Idempotent
            CliInbox_1.CliInbox.acknowledge(id);
        });
        console.log('✅ scenario 4: acknowledge deletes message file (idempotent)');
    }
    finally {
        rmTmp(tmp);
    }
}
(async () => {
    try {
        await scenarioRoundTrip();
        await scenarioReply();
        await scenarioTtlExpiry();
        await scenarioAck();
        console.log('TEST_CLI_INBOX_OK');
    }
    catch (err) {
        console.error('TEST_CLI_INBOX_FAIL', err);
        process.exit(1);
    }
})();
