import type { ExtensionAPI } from "@jaeswift/jae-coding-agent";
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
import { join } from "node:path";

interface Bookmark {
  name: string;
  path: string;
  line?: number;
  note?: string;
  timestamp: string;
}

export default function (pi: ExtensionAPI) {
  let bookmarks: Bookmark[] = [];

  function getBookmarksPath(cwd: string): string {
    return join(cwd, ".jae", "bookmarks.json");
  }

  function loadBookmarks(cwd: string): void {
    const bPath = getBookmarksPath(cwd);
    if (existsSync(bPath)) {
      try {
        bookmarks = JSON.parse(readFileSync(bPath, "utf-8"));
      } catch {
        bookmarks = [];
      }
    }
  }

  function saveBookmarks(cwd: string): void {
    const jaeDir = join(cwd, ".jae");
    if (!existsSync(jaeDir)) mkdirSync(jaeDir, { recursive: true });
    writeFileSync(getBookmarksPath(cwd), JSON.stringify(bookmarks, null, 2), "utf-8");
  }

  pi.on("session_start", async (_event, ctx) => {
    loadBookmarks(ctx.cwd);
  });

  pi.registerCommand("bookmark", {
    description: "Manage bookmarks: /bookmark [add <name> <path>[:line]] | /bookmark list | /bookmark remove <name>",
    handler: async (args, ctx) => {
      loadBookmarks(ctx.cwd);
      const parts = args.trim().split(/\s+/);
      const subcommand = parts[0] || "list";

      if (subcommand === "list" || subcommand === "ls") {
        if (bookmarks.length === 0) {
          ctx.ui.notify("No bookmarks saved. Use /bookmark add <name> <path> to add one.", "info");
          return;
        }
        const list = bookmarks
          .map((b, i) => `  ${i + 1}. ${b.name} -> ${b.path}${b.line ? `:${b.line}` : ""}${b.note ? ` (${b.note})` : ""}`)
          .join("\n");
        ctx.ui.notify(`\u{1F516} Bookmarks:\n${list}`, "info");
        return;
      }

      if (subcommand === "add") {
        const name = parts[1];
        const pathArg = parts[2];
        const note = parts.slice(3).join(" ") || undefined;
        if (!name || !pathArg) {
          ctx.ui.notify("Usage: /bookmark add <name> <path>[:line] [note]", "warning");
          return;
        }
        let filePath = pathArg;
        let line: number | undefined;
        if (pathArg.includes(":")) {
          const colonIdx = pathArg.lastIndexOf(":");
          const maybeNum = parseInt(pathArg.substring(colonIdx + 1), 10);
          if (!isNaN(maybeNum)) {
            filePath = pathArg.substring(0, colonIdx);
            line = maybeNum;
          }
        }
        // Remove existing bookmark with same name
        bookmarks = bookmarks.filter((b) => b.name !== name);
        bookmarks.push({ name, path: filePath, line, note, timestamp: new Date().toISOString() });
        saveBookmarks(ctx.cwd);
        ctx.ui.notify(`\u{1F516} Bookmark '${name}' saved: ${filePath}${line ? `:${line}` : ""}`, "info");
        return;
      }

      if (subcommand === "remove" || subcommand === "rm" || subcommand === "delete") {
        const name = parts[1];
        if (!name) {
          ctx.ui.notify("Usage: /bookmark remove <name>", "warning");
          return;
        }
        const before = bookmarks.length;
        bookmarks = bookmarks.filter((b) => b.name !== name);
        if (bookmarks.length < before) {
          saveBookmarks(ctx.cwd);
          ctx.ui.notify(`\u{1F516} Bookmark '${name}' removed.`, "info");
        } else {
          ctx.ui.notify(`Bookmark '${name}' not found.`, "warning");
        }
        return;
      }

      ctx.ui.notify("Usage: /bookmark [add|list|remove] ...", "info");
    },
  });

  pi.registerCommand("search", {
    description: "Search bookmarks: /search <query>",
    handler: async (args, ctx) => {
      loadBookmarks(ctx.cwd);
      const query = args.trim().toLowerCase();
      if (!query) {
        ctx.ui.notify("Usage: /search <query>", "warning");
        return;
      }
      const results = bookmarks.filter(
        (b) =>
          b.name.toLowerCase().includes(query) ||
          b.path.toLowerCase().includes(query) ||
          (b.note && b.note.toLowerCase().includes(query)),
      );
      if (results.length === 0) {
        ctx.ui.notify(`No bookmarks matching '${query}'.`, "info");
      } else {
        const list = results
          .map((b) => `  - ${b.name} -> ${b.path}${b.line ? `:${b.line}` : ""}${b.note ? ` (${b.note})` : ""}`)
          .join("\n");
        ctx.ui.notify(`\u{1F50D} Search results for '${query}':\n${list}`, "info");
      }
    },
  });
}
