import { dialog, ipcMain } from "electron";
import { promises as fs } from "fs";
import { Channels } from "../../shared/channels";
import * as bookmarkManager from "../bookmarks/manager";
import { normalizeBookmarkMetadata } from "../bookmarks/metadata";
import { trackBookmarkAction } from "../telemetry/posthog";
import { assertTrustedIpcSender } from "./common";

function getSafeBookmarkExportName(name: string): string {
  const safeName = name
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "");
  return safeName || "folder";
}

export function registerBookmarkHandlers(): void {
  ipcMain.handle(Channels.BOOKMARKS_GET, (event) => {
    assertTrustedIpcSender(event);
    return bookmarkManager.getState();
  });

  ipcMain.handle(
    Channels.FOLDER_CREATE,
    (event, name: string, summary?: string) => {
      assertTrustedIpcSender(event);
      trackBookmarkAction("folder_create");
      return bookmarkManager.createFolderWithSummary(name, summary);
    },
  );

  ipcMain.handle(
    Channels.BOOKMARK_SAVE,
    (
      event,
      url: string,
      title: string,
      folderId?: string,
      note?: string,
      intent?: string,
      expectedContent?: string,
      keyFields?: string[],
      agentHints?: Record<string, string>,
    ) => {
      assertTrustedIpcSender(event);
      trackBookmarkAction("save");
      const result = bookmarkManager.saveBookmarkWithPolicy(url, title, folderId, note, {
        onDuplicate: "update",
        extra: {
          ...normalizeBookmarkMetadata({
            intent,
            expectedContent,
            keyFields,
            agentHints,
          }),
        },
      });
      if (!result.bookmark) {
        throw new Error("Bookmark save failed");
      }
      return result.bookmark;
    },
  );

  ipcMain.handle(
    Channels.BOOKMARK_UPDATE,
    (
      event,
      id: string,
      updates: {
        title?: string;
        note?: string;
        folderId?: string;
        intent?: string;
        expectedContent?: string;
        keyFields?: string[];
        agentHints?: Record<string, string>;
      },
    ) => {
      assertTrustedIpcSender(event);
      trackBookmarkAction("save");
      return bookmarkManager.updateBookmark(id, updates);
    },
  );

  ipcMain.handle(Channels.BOOKMARK_REMOVE, (event, id: string) => {
    assertTrustedIpcSender(event);
    trackBookmarkAction("remove");
    return bookmarkManager.removeBookmark(id);
  });

  ipcMain.handle(
    Channels.BOOKMARKS_EXPORT_HTML,
    async (event, options?: { includeNotes?: boolean }) => {
      assertTrustedIpcSender(event);
      const { canceled, filePath } = await dialog.showSaveDialog({
        title: "Export Bookmarks",
        defaultPath: "vessel-bookmarks.html",
        filters: [{ name: "HTML Bookmarks", extensions: ["html"] }],
      });
      if (canceled || !filePath) return null;

      const content = bookmarkManager.exportBookmarksHtml({
        includeNotes: options?.includeNotes ?? false,
      });
      await fs.writeFile(filePath, content, "utf-8");
      trackBookmarkAction("export");
      return {
        filePath,
        count: bookmarkManager.getState().bookmarks.length,
      };
    },
  );

  ipcMain.handle(Channels.BOOKMARKS_EXPORT_JSON, async (event) => {
    assertTrustedIpcSender(event);
    const { canceled, filePath } = await dialog.showSaveDialog({
      title: "Export Vessel Bookmark Archive",
      defaultPath: "vessel-bookmarks.json",
      filters: [{ name: "Vessel Bookmark Archive", extensions: ["json"] }],
    });
    if (canceled || !filePath) return null;

    const content = bookmarkManager.exportBookmarksJson();
    await fs.writeFile(filePath, content, "utf-8");
    trackBookmarkAction("export");
    return {
      filePath,
      count: bookmarkManager.getState().bookmarks.length,
    };
  });

  ipcMain.handle(
    Channels.FOLDER_EXPORT_HTML,
    async (event, folderId: string, options?: { includeNotes?: boolean }) => {
      assertTrustedIpcSender(event);
      const folder = bookmarkManager.getFolder(folderId);
      if (!folder) return null;

      const { canceled, filePath } = await dialog.showSaveDialog({
        title: `Export ${folder.name}`,
        defaultPath: `vessel-bookmarks-${getSafeBookmarkExportName(folder.name)}.html`,
        filters: [{ name: "HTML Bookmarks", extensions: ["html"] }],
      });
      if (canceled || !filePath) return null;

      const result = bookmarkManager.exportBookmarkFolderHtml(folderId, {
        includeNotes: options?.includeNotes ?? true,
      });
      if (!result) return null;

      await fs.writeFile(filePath, result.content, "utf-8");
      trackBookmarkAction("export");
      return {
        filePath,
        count: result.count,
      };
    },
  );

  ipcMain.handle(Channels.BOOKMARKS_IMPORT_HTML, async (event) => {
    assertTrustedIpcSender(event);
    const { canceled, filePaths } = await dialog.showOpenDialog({
      title: "Import Bookmarks",
      filters: [
        { name: "Bookmark Files", extensions: ["html", "htm"] },
      ],
      properties: ["openFile"],
    });
    if (canceled || filePaths.length === 0) return null;
    const content = await fs.readFile(filePaths[0], "utf-8");
    trackBookmarkAction("import");
    return bookmarkManager.importBookmarksFromHtml(content);
  });

  ipcMain.handle(Channels.BOOKMARKS_IMPORT_JSON, async (event) => {
    assertTrustedIpcSender(event);
    const { canceled, filePaths } = await dialog.showOpenDialog({
      title: "Import Bookmarks",
      filters: [
        { name: "Vessel Bookmark Archive", extensions: ["json"] },
      ],
      properties: ["openFile"],
    });
    if (canceled || filePaths.length === 0) return null;
    const content = await fs.readFile(filePaths[0], "utf-8");
    trackBookmarkAction("import");
    return bookmarkManager.importBookmarksFromJson(content);
  });

  ipcMain.handle(Channels.FOLDER_REMOVE, (event, id: string, deleteContents?: boolean) => {
    assertTrustedIpcSender(event);
    trackBookmarkAction("folder_remove");
    return bookmarkManager.removeFolder(id, deleteContents ?? false);
  });

  ipcMain.handle(
    Channels.FOLDER_RENAME,
    (event, id: string, newName: string, summary?: string) => {
      assertTrustedIpcSender(event);
      return bookmarkManager.renameFolder(id, newName, summary);
    },
  );
}
