"use strict";
/**
 * test_agent_bridge_e2e — v1.11.0 regression suite.
 *
 * End-to-end smoke without spawning the full daemon: publish a manifest,
 * stand up a fake HTTP server that validates the manifest token via Basic
 * Auth, and verify the round-trip. This proves the discovery contract
 * (manifest → port → token → HTTP) holds without requiring real Telegram
 * credentials.
 *
 * Asserts:
 *   1. discover() finds the published manifest
 *   2. Basic Auth with the manifest token succeeds (200)
 *   3. Wrong token rejected (403)
 *   4. Missing auth rejected (401)
 */
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 http = __importStar(require("http"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const GatewayManifest = __importStar(require("./orchestrator/util/GatewayManifest"));
const AgentDiscovery_1 = require("./cli/AgentDiscovery");
const GatewayManifest_1 = require("./orchestrator/util/GatewayManifest");
function assert(cond, msg) {
    if (!cond)
        throw new Error(`assertion failed: ${msg}`);
}
function mkTmp() {
    return fs.mkdtempSync(path.join(os.tmpdir(), 'bridge-e2e-test-'));
}
function rmTmp(dir) {
    try {
        fs.rmSync(dir, { recursive: true, force: true });
    }
    catch { /* ignore */ }
}
// Mini daemon — accepts a mutable "expected token" ref so we can publish the
// manifest AFTER the server is up and configure auth post-hoc.
function startMiniDaemon(tokenRef) {
    return new Promise((resolve) => {
        const server = http.createServer((req, res) => {
            const auth = String(req.headers.authorization || '');
            if (!auth.startsWith('Basic ')) {
                res.writeHead(401, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify({ ok: false, error: 'auth_required' }));
                return;
            }
            const decoded = Buffer.from(auth.slice(6), 'base64').toString('utf-8');
            const sepIdx = decoded.indexOf(':');
            const user = sepIdx >= 0 ? decoded.slice(0, sepIdx) : decoded;
            const pass = sepIdx >= 0 ? decoded.slice(sepIdx + 1) : '';
            if (user !== GatewayManifest_1.MANIFEST_AUTH_USER || pass !== tokenRef.value) {
                res.writeHead(403, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify({ ok: false, error: 'forbidden' }));
                return;
            }
            res.writeHead(200, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ ok: true, path: req.url }));
        });
        server.listen(0, '127.0.0.1', () => {
            const port = server.address().port;
            resolve({
                port,
                close: () => new Promise((r) => server.close(() => r())),
            });
        });
    });
}
function postWithAuth(port, authHeader, urlPath, body) {
    return new Promise((resolve, reject) => {
        const payload = Buffer.from(JSON.stringify(body), 'utf-8');
        const headers = {
            'Content-Type': 'application/json',
            'Content-Length': String(payload.length),
        };
        if (authHeader)
            headers['Authorization'] = authHeader;
        const req = http.request({
            host: '127.0.0.1', port, method: 'POST', path: urlPath, headers,
        }, (res) => {
            const chunks = [];
            res.on('data', (c) => chunks.push(c instanceof Buffer ? c : Buffer.from(c)));
            res.on('end', () => {
                const text = Buffer.concat(chunks).toString('utf-8');
                let parsed = null;
                try {
                    parsed = JSON.parse(text);
                }
                catch { /* */ }
                resolve({ status: res.statusCode || 0, json: parsed });
            });
        });
        req.on('error', reject);
        req.write(payload);
        req.end();
    });
}
function manifestAuthHeader(token) {
    return `Basic ${Buffer.from(`${GatewayManifest_1.MANIFEST_AUTH_USER}:${token}`, 'utf-8').toString('base64')}`;
}
async function scenarioE2E() {
    const tmp = mkTmp();
    const prevState = process.env.OPENLIFE_STATE_DIR;
    const prevHome = process.env.HOME;
    process.env.OPENLIFE_STATE_DIR = tmp;
    process.env.HOME = tmp;
    const tokenRef = { value: '' };
    const mini = await startMiniDaemon(tokenRef);
    try {
        // Publish manifest pointing at the mini daemon's actual port
        const rec = GatewayManifest.publish({
            port: mini.port,
            profile: 'autonomous',
            telegram: { enabled: false, allowedUserId: null },
            version: '1.11.0-test',
        });
        // Tell mini daemon what token to expect (set the shared ref)
        tokenRef.value = rec.token;
        // Discovery should find the manifest
        const info = (0, AgentDiscovery_1.discover)();
        assert(info.alive === true, 'discover must report alive');
        assert(info.manifest !== null, 'manifest must be present');
        assert(info.manifest.token === rec.token, 'discovered token matches');
        assert(info.manifest.port === mini.port, 'discovered port matches');
        // Happy path — correct auth
        const ok = await postWithAuth(mini.port, manifestAuthHeader(rec.token), '/api/v1/core/run', { verb: 'status' });
        assert(ok.status === 200, `expected 200, got ${ok.status}`);
        assert(ok.json?.ok === true, 'mini echoes ok=true');
        // Wrong token → 403
        const bad = await postWithAuth(mini.port, manifestAuthHeader('wrong-token'), '/api/v1/core/run', { verb: 'status' });
        assert(bad.status === 403, `expected 403 with wrong token, got ${bad.status}`);
        // No auth header → 401
        const noAuth = await postWithAuth(mini.port, null, '/api/v1/core/run', { verb: 'status' });
        assert(noAuth.status === 401, `expected 401 without auth, got ${noAuth.status}`);
    }
    finally {
        await mini.close();
        GatewayManifest.remove();
        if (prevState === undefined)
            delete process.env.OPENLIFE_STATE_DIR;
        else
            process.env.OPENLIFE_STATE_DIR = prevState;
        if (prevHome === undefined)
            delete process.env.HOME;
        else
            process.env.HOME = prevHome;
        rmTmp(tmp);
    }
    console.log('✅ scenario: e2e discover + auth round-trip (200/403/401)');
}
(async () => {
    try {
        await scenarioE2E();
        console.log('TEST_AGENT_BRIDGE_E2E_OK');
    }
    catch (err) {
        console.error('TEST_AGENT_BRIDGE_E2E_FAIL', err);
        process.exit(1);
    }
})();
