"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const http_1 = __importDefault(require("http"));
// We will start the runner server on port 3334
const PORT = 3334;
const BASE_URL = `http://localhost:${PORT}`;
console.log("🧪 Starting AgentRunner Hardening Test Suite...");
// Set up environment variables
const env = {
    ...process.env,
    PORT: String(PORT),
    AGENT_RUNNER_SECRET: "test-secret-123",
    GOOGLE_API_KEY: "dummy-key-for-testing", // Pass dummy key to avoid Gemini API initialization crash
    VIBN_API_URL: "http://localhost:3335", // Mock backend
};
// Start mock backend on port 3335 to catch PATCH callbacks and verify headers
let receivedHeaders = null;
let receivedBody = null;
const mockBackend = http_1.default.createServer((req, res) => {
    receivedHeaders = req.headers;
    let body = "";
    req.on("data", (chunk) => {
        body += chunk;
    });
    req.on("end", () => {
        try {
            receivedBody = JSON.parse(body);
        }
        catch {
            receivedBody = body;
        }
        res.writeHead(200, { "Content-Type": "application/json" });
        res.end(JSON.stringify({ ok: true }));
    });
});
mockBackend.listen(3335, () => {
    console.log("✓ Mock backend server listening on port 3335");
});
// Spawn the runner server
const serverProcess = (0, child_process_1.spawn)("npx", ["ts-node", "src/server.ts"], {
    env,
    stdio: "pipe",
});
// Wait for server to start
serverProcess.stdout.on("data", (data) => {
    const output = data.toString();
    console.log(`[Server Out] ${output.trim()}`);
});
serverProcess.stderr.on("data", (data) => {
    console.error(`[Server Err] ${data.toString()}`);
});
// Helper function to sleep
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function runTests() {
    // Wait 4 seconds for server to boot
    await sleep(4000);
    let passed = 0;
    let failed = 0;
    const assert = (condition, message) => {
        if (condition) {
            console.log(`  🟢 PASSED: ${message}`);
            passed++;
        }
        else {
            console.error(`  🔴 FAILED: ${message}`);
            failed++;
        }
    };
    try {
        // Test 1: Empty appPath should be accepted and fall back to "."
        console.log("\n1️⃣ Testing appPath empty string fallback...");
        const res1 = await fetch(`${BASE_URL}/agent/execute`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                sessionId: "test-session-1",
                projectId: "test-project-1",
                task: "Test empty appPath",
                appPath: "", // Empty string!
                giteaRepo: "test-repo",
            }),
        });
        assert(res1.status === 202, `Should return 202, got ${res1.status}`);
        const data1 = (await res1.json());
        assert(data1.sessionId === "test-session-1", `Should return correct sessionId, got ${data1.sessionId}`);
        // Test 2: Missing sessionId should return 400
        console.log("\n2️⃣ Testing missing required parameters (sessionId)...");
        const res2 = await fetch(`${BASE_URL}/agent/execute`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                projectId: "test-project-1",
                task: "Test missing sessionId",
                appPath: ".",
            }),
        });
        assert(res2.status === 400, `Should return 400, got ${res2.status}`);
        // Test 3: Emergency callback headers should include x-agent-runner-secret
        console.log("\n3️⃣ Testing early failure callback headers...");
        // Trigger a clone failure by passing a malformed giteaRepo containing slash,
        // which triggers clone instead of default workspace but will fail clone.
        console.log("Triggering clone failure on mock Gitea...");
        const res3 = await fetch(`${BASE_URL}/agent/execute`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                sessionId: "test-session-3",
                projectId: "test-project-3",
                task: "Trigger crash",
                appPath: ".",
                giteaRepo: "invalid_owner/invalid_repo",
            }),
        });
        assert(res3.status === 202, `Should return 202 Accepted, got ${res3.status}`);
        // Wait for server to process async task and fail, calling our mock backend PATCH
        console.log("Waiting for runner callback on mock backend...");
        await sleep(4000);
        assert(receivedHeaders !== null, "Should call mock backend PATCH endpoint");
        if (receivedHeaders) {
            assert(receivedHeaders["x-agent-runner-secret"] === "test-secret-123", `Callback should include secret header 'test-secret-123', got '${receivedHeaders["x-agent-runner-secret"]}'`);
            assert(receivedBody && receivedBody.status === "failed", `Callback body should have status 'failed', got '${receivedBody?.status}'`);
        }
    }
    catch (err) {
        console.error("Test execution failed with exception:", err);
    }
    finally {
        console.log("\n🧹 Cleaning up test servers...");
        serverProcess.kill();
        mockBackend.close();
        console.log(`\n📊 Tests complete. Passed: ${passed}, Failed: ${failed}`);
        process.exit(failed > 0 ? 1 : 0);
    }
}
runTests();
