/**
 * Integration test: verifies query params survive the full pipeline
 * TS (ScenarioGenerationService) → JSON file → Go binary → generated test code
 *
 * Requires: @skyramp/skyramp native dylib (skips if not available)
 */
import fs from "fs";
import path from "path";
import os from "os";
import { ScenarioGenerationService } from "./ScenarioGenerationService.js";
let SkyrampClient;
try {
    SkyrampClient = require("@skyramp/skyramp").SkyrampClient;
}
catch {
    SkyrampClient = null;
}
// These tests require the native Go binary which is platform-specific.
// Skip in CI or when the binary isn't available for this OS/arch.
const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS);
const describeIfBinary = SkyrampClient && !isCI ? describe : describe.skip;
function buildTrace(overrides) {
    const service = new ScenarioGenerationService();
    return service.generateTraceRequestFromInput({
        scenarioName: "integration-qp-test",
        destination: "localhost",
        baseURL: "http://localhost:8080",
        method: "GET",
        path: "/api/v1/items",
        outputDir: os.tmpdir(),
        authHeader: "",
        authScheme: "",
        ...overrides,
    });
}
describeIfBinary("QueryParams integration: TS → JSON → Go binary → generated code", () => {
    let tmpDir;
    let outputDir;
    let client;
    // Go dylib cold-starts can take a few seconds
    jest.setTimeout(15000);
    beforeAll(() => {
        client = new SkyrampClient();
    });
    afterAll(() => {
        client?.close?.();
    });
    beforeEach(() => {
        tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "skyramp-qp-integration-"));
        outputDir = path.join(tmpDir, "output");
        fs.mkdirSync(outputDir);
    });
    afterEach(() => {
        fs.rmSync(tmpDir, { recursive: true, force: true });
    });
    async function generateFromTrace(trace) {
        const traceFile = path.join(tmpDir, "scenario.json");
        fs.writeFileSync(traceFile, JSON.stringify([trace], null, 2));
        await client.generateRestTest({
            testType: "integration",
            language: "python",
            framework: "pytest",
            outputDir,
            force: true,
            traceFilePath: traceFile,
        });
        const files = fs.readdirSync(outputDir).filter((f) => f.endsWith(".py"));
        if (files.length === 0)
            throw new Error("No generated test file found");
        return fs.readFileSync(path.join(outputDir, files[0]), "utf8");
    }
    it("bracket-notation keys pass through to generated test code", async () => {
        // Simulates: GET /api/v1/items?filter[status][_eq]=published&limit=25
        const trace = buildTrace({
            queryParams: '{"filter[status][_eq]":"published","limit":25}',
        });
        expect(trace).not.toBeNull();
        expect(trace.QueryParams).toEqual({
            "filter[status][_eq]": ["published"],
            "limit": ["25"],
        });
        const code = await generateFromTrace(trace);
        expect(code).toContain("filter[status][_eq]");
        expect(code).toContain("published");
        expect(code).toContain("limit");
        expect(code).toContain("25");
    });
    it("simple flat params pass through to generated test code", async () => {
        // Simulates: GET /api/v1/items?page=2&status=active
        const trace = buildTrace({
            queryParams: '{"page":2,"status":"active"}',
        });
        expect(trace).not.toBeNull();
        expect(trace.QueryParams).toEqual({
            page: ["2"],
            status: ["active"],
        });
        const code = await generateFromTrace(trace);
        expect(code).toContain("page");
        expect(code).toContain("2");
        expect(code).toContain("status");
        expect(code).toContain("active");
    });
    it("JSON-encoded string value (Elasticsearch-style) passes through intact", async () => {
        // Simulates: GET /search?source={"query":{"match":{"name":"bear"}}}
        const trace = buildTrace({
            queryParams: '{"source":"{\\"query\\":{\\"match\\":{\\"name\\":\\"bear\\"}}}"}',
        });
        expect(trace).not.toBeNull();
        expect(trace.QueryParams).toEqual({
            source: ['{"query":{"match":{"name":"bear"}}}'],
        });
        const code = await generateFromTrace(trace);
        expect(code).toContain("source");
        expect(code).toMatch(/query.*match.*name.*bear/);
    });
    it("array params are comma-joined into a single value in generated code", async () => {
        // Simulates: GET /products?tags=sale,new
        const trace = buildTrace({
            queryParams: '{"tags":["sale","new"]}',
        });
        expect(trace).not.toBeNull();
        expect(trace.QueryParams).toEqual({
            tags: ["sale,new"],
        });
        const code = await generateFromTrace(trace);
        expect(code).toContain("tags");
        expect(code).toContain("sale,new");
    });
    it("null params are omitted — not present in generated code", async () => {
        // null means "don't include this param" — same as axios/fetch omitting undefined
        const trace = buildTrace({
            queryParams: '{"limit":10,"cursor":null}',
        });
        expect(trace).not.toBeNull();
        expect(trace.QueryParams).toEqual({
            limit: ["10"],
        });
        const code = await generateFromTrace(trace);
        expect(code).toContain("limit");
        expect(code).toContain("10");
        expect(code).not.toContain("cursor");
    });
    it("nested object fallback produces valid JSON string in generated code", async () => {
        // LLM mistakenly sends nested object — service JSON-stringifies it
        const trace = buildTrace({
            queryParams: '{"filter":{"status":"active"}}',
        });
        expect(trace).not.toBeNull();
        expect(trace.QueryParams).toEqual({
            filter: ['{"status":"active"}'],
        });
        const code = await generateFromTrace(trace);
        expect(code).toContain("filter");
        expect(code).not.toContain("[object Object]");
        expect(code).not.toContain("map[");
    });
});
