import { z } from "zod";
import { getLogger } from "../../../../util/logger.js";
import { sendUserMessageChannel } from "../../../state-machine/helpers/peer.js";
import { createToolFactory, ToolCategory, PermissionLevel } from "../types.js";
/**
 * updateTestCaseStatus - Updates the status of a specific test case during a test run.
 *
 * This tool:
 * 1. Validates that the test case ID exists
 * 2. Updates the status in clark context (server-side tracking)
 * 3. Sends test_case_update message to UI
 *
 * Only accessible to the TEST subagent (ToolCategory.TEST).
 */
export const updateTestCaseStatusToolFactory = createToolFactory("updateTestCaseStatus", ({ clark, services, }) => {
    const logger = getLogger();
    return {
        description: `
Update the status of a specific test case during the test run.

**IMPORTANT**: You MUST call this tool:
1. BEFORE starting each test case - set status to "running"
2. AFTER completing each test case - set status to "passed" or "failed"

Example workflow for test case "test-1":
1. updateTestCaseStatus({ testCaseId: "test-1", status: "running" })
2. ... perform browser actions for the test ...
3. updateTestCaseStatus({ testCaseId: "test-1", status: "passed" })

This ensures the UI shows real-time progress of which tests are running and their results.
`,
        category: ToolCategory.TEST,
        defaultPermission: PermissionLevel.ALLOW,
        readOnly: true,
        inputSchema: z.object({
            testCaseId: z
                .string()
                .describe("ID of the test case to update (e.g., 'test-1')"),
            status: z
                .enum(["running", "passed", "failed", "skipped"])
                .describe("New status for the test case: 'running' when starting, 'passed' or 'failed' when complete, 'skipped' when user skips the test"),
        }),
        execute: async ({ testCaseId, status }) => {
            const testRunId = clark.context.currentTestRunId;
            const testCases = clark.context.currentTestCases;
            if (!testRunId) {
                logger.warn(`[TestSubagent] No active test run for updateTestCaseStatus`);
                return {
                    success: false,
                    error: "No active test run",
                };
            }
            const existingStatuses = clark.context.testCaseStatuses;
            const existingStatus = existingStatuses?.get(testCaseId);
            if (existingStatus === "skipped" && status !== "skipped") {
                // Prevent the test subagent from "un-skipping" a test case that the user skipped.
                // This keeps UI + server-side reconciliation consistent.
                logger.info(`[TestSubagent] Ignoring status update for skipped test case '${testCaseId}': attempted '${status}'`);
                return {
                    success: false,
                    error: `Test case '${testCaseId}' was skipped by the user`,
                };
            }
            // Validate that the test case exists
            if (testCases && testCases.length > 0) {
                const testCaseExists = testCases.some((tc) => tc.id === testCaseId);
                if (!testCaseExists) {
                    logger.warn(`[TestSubagent] Test case ID '${testCaseId}' not found in current test cases`);
                    // Don't fail - allow the update anyway in case of LLM inconsistency
                }
            }
            // Update status in context for server-side tracking
            const testCaseStatuses = clark.context.testCaseStatuses ??
                new Map();
            testCaseStatuses.set(testCaseId, status);
            // Clear sticky skip instruction once the agent starts a different test case.
            // This prevents the skip instruction from being injected repeatedly after the agent moves on.
            const skipRequestedForTestCase = clark.context.skipRequestedForTestCase;
            clark.updateContext({
                testCaseStatuses,
                ...(status === "running" &&
                    skipRequestedForTestCase &&
                    testCaseId !== skipRequestedForTestCase
                    ? { skipRequestedForTestCase: undefined }
                    : {}),
            });
            // Send test_case_update message to UI
            const sendUserMessage = sendUserMessageChannel(clark, services.chatSessionStore);
            await sendUserMessage({
                type: "test_case_update",
                testRunId,
                testCaseId,
                testCaseStatus: status,
                role: "assistant",
                content: "",
            });
            logger.info(`[TestSubagent] Test case '${testCaseId}' status updated to '${status}'`);
            return {
                success: true,
                testCaseId,
                status,
            };
        },
        getSummary: (input) => {
            return {
                input: `testCaseId: ${input.testCaseId}`,
                output: `Status: ${input.status}`,
            };
        },
    };
});
//# sourceMappingURL=update-test-case-status.js.map