jest.mock("@skyramp/skyramp", () => ({
    WorkspaceConfigManager: { create: jest.fn() },
}));
import { runUiAnalyzeChanges } from "./uiAnalyzeChangesTool.js";
import * as workspaceAuth from "../../utils/workspaceAuth.js";
import * as fs from "fs";
import * as os from "os";
import * as path from "path";
function makeRepoWithDiff(changedFiles) {
    const dir = fs.mkdtempSync(path.join(os.tmpdir(), "skyramp-uiac-test-"));
    // Write .skyramp_git_diff with the requested file changes — match the
    // format the runtime uses (raw `diff --git a/X b/X` block).
    const diff = changedFiles
        .map((f) => `diff --git a/${f} b/${f}\n+++ b/${f}\n@@ -0,0 +1,1 @@\n+x`)
        .join("\n");
    fs.writeFileSync(path.join(dir, ".skyramp_git_diff"), diff);
    return dir;
}
describe("runUiAnalyzeChanges", () => {
    let readSpy;
    beforeEach(() => {
        readSpy = jest.spyOn(workspaceAuth, "readWorkspaceConfigRaw");
    });
    afterEach(() => {
        readSpy.mockRestore();
    });
    it("returns empty changedFrontendFiles for backend-only diffs", async () => {
        readSpy.mockResolvedValue({ services: [] });
        const repo = makeRepoWithDiff(["api/handlers/users.ts"]);
        const result = await runUiAnalyzeChanges({ repositoryPath: repo });
        expect(result.uiContext.changedFrontendFiles).toEqual([]);
        expect(result.uiContext.candidateUiPages).toEqual([]);
        expect(result.instructions).toMatch(/no UI changes/i);
        fs.rmSync(repo, { recursive: true, force: true });
    });
    it("returns candidateUiPages and capture instructions for frontend diffs", async () => {
        readSpy.mockResolvedValue({
            services: [{ serviceName: "frontend", api: { baseUrl: "http://localhost:3000" } }],
        });
        const repo = makeRepoWithDiff(["frontend/src/components/Cart.tsx"]);
        const result = await runUiAnalyzeChanges({ repositoryPath: repo });
        expect(result.uiContext.changedFrontendFiles.length).toBeGreaterThan(0);
        expect(result.uiContext.candidateUiPages.length).toBeGreaterThan(0);
        expect(result.instructions).toMatch(/browser_navigate/);
        expect(result.instructions).toMatch(/browser_blueprint/);
        expect(result.instructions).toMatch(/skyramp_analyze_changes/);
        // Captures stay in agent's tool-result history; we no longer thread them
        // back through analyze_changes as a param.
        expect(result.instructions).not.toMatch(/capturedBlueprints/);
        fs.rmSync(repo, { recursive: true, force: true });
    });
    it("includes inline-credentials login step in non-testbot mode", async () => {
        // SKYRAMP_FEATURE_TESTBOT is not set here, so the tool emits the
        // credentials inline rather than referencing the testbot's
        // <ui-credentials> context tag (which doesn't exist outside testbot).
        delete process.env.SKYRAMP_FEATURE_TESTBOT;
        readSpy.mockResolvedValue({
            services: [{ serviceName: "frontend", api: { baseUrl: "http://localhost:3000" } }],
        });
        const repo = makeRepoWithDiff(["frontend/src/components/Cart.tsx"]);
        const result = await runUiAnalyzeChanges({
            repositoryPath: repo,
            uiCredentials: "admin@example.com:admin",
        });
        expect(result.instructions).toMatch(/log in/i);
        expect(result.instructions).toContain("admin@example.com:admin");
        fs.rmSync(repo, { recursive: true, force: true });
    });
    it("references the <ui-credentials> testbot context tag in testbot mode", async () => {
        process.env.SKYRAMP_FEATURE_TESTBOT = "1";
        try {
            readSpy.mockResolvedValue({
                services: [{ serviceName: "frontend", api: { baseUrl: "http://localhost:3000" } }],
            });
            const repo = makeRepoWithDiff(["frontend/src/components/Cart.tsx"]);
            const result = await runUiAnalyzeChanges({
                repositoryPath: repo,
                uiCredentials: "admin@example.com:admin",
            });
            expect(result.instructions).toMatch(/log in/i);
            expect(result.instructions).toContain("ui-credentials");
            // Inline credentials should NOT leak in testbot mode (the
            // <ui-credentials> tag is the secure carrier in that flow).
            expect(result.instructions).not.toContain("admin@example.com:admin");
            fs.rmSync(repo, { recursive: true, force: true });
        }
        finally {
            delete process.env.SKYRAMP_FEATURE_TESTBOT;
        }
    });
    it("instructs the agent to proceed to analyze_changes (source-grounded) when frontend baseUrl unresolvable", async () => {
        readSpy.mockResolvedValue(null); // no workspace yml
        const repo = makeRepoWithDiff(["frontend/src/components/Cart.tsx"]);
        const result = await runUiAnalyzeChanges({ repositoryPath: repo });
        expect(result.uiContext.changedFrontendFiles.length).toBeGreaterThan(0);
        expect(result.uiContext.candidateUiPages).toEqual([]);
        expect(result.instructions).toMatch(/source-grounded/i);
        fs.rmSync(repo, { recursive: true, force: true });
    });
});
