import { CloseBotClient, ok, err } from "../client.js";
import type { ToolDefinition, ToolResult, FileDto, WebscrapePageDto, WebscrapePageUpdateDto, UploadWebscrapeToSourceInput } from "../types.js";

export const tools: ToolDefinition[] = [
  {
    name: "list_files",
    description: "List all files in the knowledge base library",
    inputSchema: { type: "object", properties: {} },
  },
  {
    name: "get_file",
    description: "Get metadata for a specific file",
    inputSchema: {
      type: "object",
      properties: {
        fileId: { type: "string", description: "The file ID" },
      },
      required: ["fileId"],
    },
  },
  {
    name: "delete_file",
    description: "Delete a file from the library",
    inputSchema: {
      type: "object",
      properties: {
        fileId: { type: "string", description: "The file ID" },
      },
      required: ["fileId"],
    },
  },
  {
    name: "view_file_content",
    description: "View the content of a file",
    inputSchema: {
      type: "object",
      properties: {
        fileId: { type: "string", description: "The file ID" },
      },
      required: ["fileId"],
    },
  },
  {
    name: "get_scrape_pages",
    description: "Get the web scrape pages for a file",
    inputSchema: {
      type: "object",
      properties: {
        fileId: { type: "string", description: "The file ID" },
      },
      required: ["fileId"],
    },
  },
  {
    name: "update_scrape_pages",
    description: "Update the web scrape pages for a file (enable/disable specific URLs)",
    inputSchema: {
      type: "object",
      properties: {
        fileId: { type: "string", description: "The file ID" },
        pages: {
          type: "array",
          description: "Array of page configs",
          items: {
            type: "object",
            properties: {
              url: { type: "string", description: "Page URL" },
              enabled: { type: "boolean", description: "Whether the page is enabled" },
            },
          },
        },
      },
      required: ["fileId", "pages"],
    },
  },
  {
    name: "create_web_scrape",
    description: "Create a new web scrape file from a URL",
    inputSchema: {
      type: "object",
      properties: {
        scrapeUrl: { type: "string", description: "URL to scrape" },
        maxBreadth: { type: "number", description: "Maximum breadth of the scrape" },
        maxDepth: { type: "number", description: "Maximum depth of the scrape" },
      },
      required: ["scrapeUrl"],
    },
  },
  {
    name: "attach_file_to_source",
    description: "Attach a library file to a source for knowledge base use",
    inputSchema: {
      type: "object",
      properties: {
        fileId: { type: "string", description: "The file ID" },
        sourceId: { type: "string", description: "The source ID" },
      },
      required: ["fileId", "sourceId"],
    },
  },
  {
    name: "detach_file_from_source",
    description: "Detach a library file from a source",
    inputSchema: {
      type: "object",
      properties: {
        fileId: { type: "string", description: "The file ID" },
        sourceId: { type: "string", description: "The source ID" },
      },
      required: ["fileId", "sourceId"],
    },
  },
  {
    name: "upload_file",
    description: "Upload a file to the library. Provide base64-encoded file content.",
    inputSchema: {
      type: "object",
      properties: {
        fileName: { type: "string", description: "File name with extension" },
        fileContent: { type: "string", description: "Base64-encoded file content" },
        mimeType: { type: "string", description: "MIME type of the file (e.g., text/plain, application/pdf)" },
      },
      required: ["fileName", "fileContent"],
    },
  },
  {
    name: "replace_file_content",
    description: "Replace the content of an existing file. Provide base64-encoded new content.",
    inputSchema: {
      type: "object",
      properties: {
        fileId: { type: "string", description: "The file ID" },
        fileName: { type: "string", description: "File name with extension" },
        fileContent: { type: "string", description: "Base64-encoded new file content" },
        mimeType: { type: "string", description: "MIME type of the file" },
      },
      required: ["fileId", "fileContent"],
    },
  },
];

export async function handler(
  client: CloseBotClient,
  name: string,
  args: Record<string, unknown>
): Promise<ToolResult> {
  try {
    switch (name) {
      case "list_files":
        return ok(await client.get<FileDto[]>("/library/files"));

      case "get_file":
        return ok(await client.get<FileDto>(`/library/files/${args.fileId}`));

      case "delete_file":
        return ok(await client.delete(`/library/files/${args.fileId}`));

      case "view_file_content":
        return ok(await client.get(`/library/files/${args.fileId}/view`));

      case "get_scrape_pages":
        return ok(
          await client.get<WebscrapePageDto[]>(
            `/library/files/${args.fileId}/scrape-pages`
          )
        );

      case "update_scrape_pages": {
        const body: WebscrapePageUpdateDto = {
          pages: args.pages as WebscrapePageDto[],
        };
        return ok(
          await client.put(`/library/files/${args.fileId}/scrape-pages`, body)
        );
      }

      case "create_web_scrape": {
        const body: UploadWebscrapeToSourceInput = {
          scrapeUrl: args.scrapeUrl as string,
          maxBreadth: (args.maxBreadth as number) || 10,
          maxDepth: (args.maxDepth as number) || 2,
        };
        return ok(await client.post("/library/webscrape", body));
      }

      case "attach_file_to_source":
        return ok(
          await client.post(
            `/library/files/${args.fileId}/source/${args.sourceId}`
          )
        );

      case "detach_file_from_source":
        return ok(
          await client.delete(
            `/library/files/${args.fileId}/source/${args.sourceId}`
          )
        );

      case "upload_file": {
        const buffer = Buffer.from(args.fileContent as string, "base64");
        const blob = new Blob([buffer], {
          type: (args.mimeType as string) || "application/octet-stream",
        });
        const formData = new FormData();
        formData.append("file", blob, args.fileName as string);
        return ok(await client.postFormData("/library/files", formData));
      }

      case "replace_file_content": {
        const buffer = Buffer.from(args.fileContent as string, "base64");
        const blob = new Blob([buffer], {
          type: (args.mimeType as string) || "application/octet-stream",
        });
        const formData = new FormData();
        formData.append(
          "newFile",
          blob,
          (args.fileName as string) || "file"
        );
        return ok(
          await client.putFormData(`/library/files/${args.fileId}`, formData)
        );
      }

      default:
        return err(`Unknown tool: ${name}`);
    }
  } catch (error) {
    return err(error);
  }
}
