import path from "node:path";
import z from "zod";
import { AiEntityType, AiPermissionType, } from "@superblocksteam/library-shared/types";
import { Paths } from "../../const.js";
import { renderPath } from "../../transform/shared.js";
import { createToolFactory, ToolCategory, PermissionLevel, } from "../tools2/types.js";
import { debugCache, createTypeScriptCheckFunction } from "./debug-cache.js";
import { parseGeneratedApiPath } from "./shared-helpers.js";
/**
 * Determines the type of file being deleted.
 */
function getDeleteFileType(filePath) {
    // Check if it's an API
    const apiPathParams = parseGeneratedApiPath(filePath);
    if (apiPathParams) {
        return "api";
    }
    // Check if it's a page
    if (filePath.startsWith("pages/")) {
        return "page";
    }
    return "file";
}
/**
 * Check if file deletion requires user confirmation.
 * Prompts for:
 * - APIs (always)
 * - Pages (except default Page1)
 * Allows without prompting:
 * - Default Page1
 * - All other files (components, utils, etc.)
 */
export const checkDeleteFilePermissions = async (input) => {
    // During initial tool building, no input available yet
    if (!input || !input.filePath) {
        return PermissionLevel.PROMPT;
    }
    const { filePath } = input;
    // Check if it's an API
    const apiPathParams = parseGeneratedApiPath(filePath);
    if (apiPathParams) {
        return PermissionLevel.PROMPT;
    }
    // Check if it's a page file or directory
    if (filePath.startsWith("pages/")) {
        // Extract page name from path (handles both pages/PageName.tsx and pages/PageName/)
        const pathWithoutPrefix = filePath.slice("pages/".length);
        const parts = pathWithoutPrefix.split("/");
        const pageName = parts[0]?.replace(/\.tsx$/, "") || "";
        // Skip prompt for default Page1
        if (pageName === "Page1") {
            return PermissionLevel.ALLOW;
        }
        // Prompt for other pages
        return PermissionLevel.PROMPT;
    }
    // For all other files (components, utils, etc.), allow without prompting
    return PermissionLevel.ALLOW;
};
export const buildDeleteFileToolFactory = createToolFactory("build_deleteFile", ({ clark, services, }) => {
    return {
        category: ToolCategory.FILE,
        description: `
      Deletes a file or directory from the project. This is a destructive operation that requires confirmation.
      The deletion is draftable - you can restore the file by discarding changes.

      Use this tool to:
      - Remove obsolete files or directories
      - Delete APIs that are no longer needed
      - Clean up unused components or pages

      Important:
      - Always use relative file paths
      - The file can be restored if changes are discarded
      - For APIs, this will automatically update type definitions
      - User confirmation handled by access control rules
      `,
        defaultPermission: PermissionLevel.ALLOW,
        inputSchema: z.object({
            filePath: z
                .string()
                .describe("Relative path to the file or directory to delete"),
            reason: z.string().optional().describe("Optional reason for deletion"),
        }),
        getActionName: () => ({
            future: "delete",
            past: "deleted",
            present: "deleting",
        }),
        // Format for confirmation dialog
        formatInput: (input) => {
            if (!input || !input.filePath) {
                return {
                    targets: [],
                    summary: "Delete file?",
                };
            }
            const fileType = getDeleteFileType(input.filePath);
            // Check if this is an API file - if so, show the directory instead
            const apiPathParams = parseGeneratedApiPath(input.filePath);
            if (apiPathParams) {
                const { apiName } = apiPathParams;
                const apiDirPath = renderPath(Paths.GeneratedApis, { apiName });
                return {
                    targets: [apiDirPath],
                    summary: `Ok if I delete the ${apiName} API?`,
                    details: input.reason,
                    entityType: fileType,
                    entityName: apiName,
                };
            }
            // Handle pages
            if (fileType === "page") {
                const pathWithoutPrefix = input.filePath.slice("pages/".length);
                const parts = pathWithoutPrefix.split("/");
                const pageName = parts[0]?.replace(/\.tsx$/, "") || "";
                return {
                    targets: [input.filePath],
                    summary: `Ok if I delete the ${pageName} page?`,
                    details: input.reason,
                    entityType: fileType,
                    entityName: pageName,
                };
            }
            // Handle regular files
            const fileName = path.basename(input.filePath);
            return {
                targets: [input.filePath],
                summary: `Ok if I delete ${fileName}?`,
                details: input.reason,
                entityType: fileType,
                entityName: fileName,
            };
        },
        getRequiredPermissions: (input) => {
            if (!input || !input.filePath) {
                return [];
            }
            const fileType = getDeleteFileType(input.filePath);
            // For pages, extract as PAGE entity
            if (fileType === "page") {
                return [
                    {
                        entityType: AiEntityType.PAGE,
                        entityId: undefined, // All pages are allowed to be deleted
                        permissionType: AiPermissionType.DELETE,
                    },
                ];
            }
            // For APIs, extract as API entity
            if (fileType === "api") {
                return [
                    {
                        entityType: AiEntityType.API,
                        entityId: undefined, // All APIs are allowed to be deleted
                        permissionType: AiPermissionType.DELETE,
                    },
                ];
            }
            // For other files, return empty (no entity extraction needed)
            return [];
        },
        execute: async ({ filePath, reason }) => {
            // Determine file type for response (before deletion)
            const fileType = getDeleteFileType(filePath);
            // Check if this is an API (for updating untestedApis context)
            const apiPathParams = parseGeneratedApiPath(filePath);
            await services.appShell.deleteFile(filePath);
            // Clear from API testing state and failed builds if it was an API
            if (apiPathParams) {
                const { apiName } = apiPathParams;
                clark.context.apiTestingState?.untested.delete(apiName);
                clark.context.apiTestingState?.failed.delete(apiName);
                clark.context.apiTestingState?.passed.delete(apiName);
                clark.context.apiTestingState?.denied.delete(apiName);
                clark.context.failedApiBuilds?.delete(apiName);
            }
            // Invalidate TypeScript cache
            debugCache.invalidateTypeScript();
            // Update last modification time
            clark.updateContext({
                lastFileModificationTime: Date.now(),
                runtimeErrors: [],
            });
            debugCache.invalidateContextErrors();
            // Trigger eager TypeScript check after deletion (debounced to avoid excessive checks)
            const typeCheckFunction = createTypeScriptCheckFunction(services.appShell, clark.context.abortController?.signal);
            debugCache.startEagerTypeScriptCheck(typeCheckFunction);
            // Build appropriate message based on file type
            let message;
            if (fileType === "api" && apiPathParams) {
                const apiDirPath = renderPath(Paths.GeneratedApis, {
                    apiName: apiPathParams.apiName,
                });
                message = `Successfully deleted API ${apiPathParams.apiName} (directory ${apiDirPath}). You can restore it by discarding changes.`;
            }
            else {
                message = `Successfully deleted ${filePath}. You can restore it by discarding changes.`;
            }
            return {
                filePath,
                type: fileType,
                message,
                reason,
            };
        },
        getSummary: (_input, output) => {
            const type = output.type || "file";
            return {
                output: `Deleted ${type}`,
            };
        },
    };
});
//# sourceMappingURL=build-delete-file.js.map