"use strict";
/**
 * test_gateway_manifest — v1.11.0 regression suite.
 *
 * Asserts:
 *   1. publish() writes a valid manifest + token sidecar
 *   2. refresh() updates refreshedAt without changing the token
 *   3. remove() deletes both manifest and token files
 *   4. File permissions are 0o600 on POSIX
 *
 * Standalone — throws on failure, prints TEST_GATEWAY_MANIFEST_OK on full pass.
 */
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 GatewayManifest = __importStar(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(), 'manifest-test-'));
}
function rmTmp(dir) {
    try {
        fs.rmSync(dir, { recursive: true, force: true });
    }
    catch { /* ignore */ }
}
function withStateDir(dir, fn) {
    const prev = process.env.OPENLIFE_STATE_DIR;
    process.env.OPENLIFE_STATE_DIR = dir;
    try {
        return fn();
    }
    finally {
        if (prev === undefined)
            delete process.env.OPENLIFE_STATE_DIR;
        else
            process.env.OPENLIFE_STATE_DIR = prev;
    }
}
function scenarioPublishRoundTrip() {
    const tmp = mkTmp();
    try {
        withStateDir(tmp, () => {
            const manifestPath = GatewayManifest._resolvedPath();
            const tokenPath = GatewayManifest._resolvedTokenPath();
            const rec = GatewayManifest.publish({
                port: 3000,
                profile: 'autonomous',
                telegram: { enabled: false, allowedUserId: null },
                version: '1.11.0-test',
            });
            assert(rec.token.length === 64, 'token must be 32 bytes hex (64 chars)');
            assert(rec.port === 3000, 'port should match published value');
            assert(rec.schemaVersion === 1, 'schemaVersion must be 1');
            assert(fs.existsSync(manifestPath), 'manifest file must exist');
            assert(fs.existsSync(tokenPath), 'token sidecar must exist');
            const onDisk = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
            assert(onDisk.token === rec.token, 'on-disk token must match returned token');
            assert(onDisk.refreshedAt === rec.refreshedAt, 'refreshedAt must match');
            const sidecarToken = fs.readFileSync(tokenPath, 'utf-8');
            assert(sidecarToken === rec.token, 'sidecar token mismatch');
            // POSIX permissions check (best-effort on non-Linux)
            if (process.platform === 'linux' || process.platform === 'darwin') {
                const mode = fs.statSync(manifestPath).mode & 0o777;
                assert(mode === 0o600, `manifest must be 0o600, got 0o${mode.toString(8)}`);
            }
        });
        console.log('✅ scenario 1: publish round-trip');
    }
    finally {
        rmTmp(tmp);
    }
}
function scenarioRefreshStableToken() {
    const tmp = mkTmp();
    try {
        withStateDir(tmp, () => {
            const pub = GatewayManifest.publish({ port: 4000 });
            const firstRefreshedAt = pub.refreshedAt;
            // Sleep 5ms so refreshedAt timestamp differs deterministically
            const wait = Date.now() + 5;
            while (Date.now() < wait) { /* spin */ }
            const refreshed = GatewayManifest.refresh();
            assert(refreshed !== null, 'refresh must return record');
            assert(refreshed.token === pub.token, 'refresh must not rotate the token');
            assert(refreshed.refreshedAt !== firstRefreshedAt, 'refreshedAt must advance');
            assert(refreshed.startedAt === pub.startedAt, 'startedAt must not change');
        });
        console.log('✅ scenario 2: refresh preserves token, advances refreshedAt');
    }
    finally {
        rmTmp(tmp);
    }
}
function scenarioRemoveCleansBoth() {
    const tmp = mkTmp();
    try {
        withStateDir(tmp, () => {
            GatewayManifest.publish({ port: 5000 });
            const manifestPath = GatewayManifest._resolvedPath();
            const tokenPath = GatewayManifest._resolvedTokenPath();
            assert(fs.existsSync(manifestPath) && fs.existsSync(tokenPath), 'preconditions');
            GatewayManifest.remove();
            assert(!fs.existsSync(manifestPath), 'manifest must be deleted');
            assert(!fs.existsSync(tokenPath), 'token sidecar must be deleted');
            assert(GatewayManifest.peek() === null, 'in-memory state must be cleared');
            // Idempotent
            GatewayManifest.remove();
        });
        console.log('✅ scenario 3: remove() cleans both files, idempotent');
    }
    finally {
        rmTmp(tmp);
    }
}
function scenarioRefreshBeforePublishIsNoOp() {
    const tmp = mkTmp();
    try {
        withStateDir(tmp, () => {
            // Ensure no prior state
            GatewayManifest.remove();
            const result = GatewayManifest.refresh();
            assert(result === null, 'refresh before publish must return null');
        });
        console.log('✅ scenario 4: refresh-before-publish is no-op');
    }
    finally {
        rmTmp(tmp);
    }
}
try {
    scenarioPublishRoundTrip();
    scenarioRefreshStableToken();
    scenarioRemoveCleansBoth();
    scenarioRefreshBeforePublishIsNoOp();
    console.log('TEST_GATEWAY_MANIFEST_OK');
}
catch (err) {
    console.error('TEST_GATEWAY_MANIFEST_FAIL', err);
    process.exit(1);
}
