import type { ExtensionAPI } from "@jaeswift/jae-coding-agent";
import { watch, type FSWatcher, readFileSync } from "node:fs";
import { join, relative, extname } from "node:path";

export default function (pi: ExtensionAPI) {
  let watcher: FSWatcher | null = null;
  let pairMode = false;
  let watchedFiles = new Set<string>();
  let lastChangeTime = 0;
  const DEBOUNCE_MS = 2000;

  const CODE_EXTENSIONS = new Set([
    ".ts", ".tsx", ".js", ".jsx", ".py", ".rs", ".go",
    ".java", ".c", ".cpp", ".h", ".css", ".scss",
    ".html", ".vue", ".svelte", ".rb", ".php",
    ".json", ".yaml", ".yml", ".toml", ".md",
  ]);

  const IGNORE_PATTERNS = [
    "node_modules", ".git", "dist", "build", ".jae",
    ".next", ".cache", "__pycache__", "target",
  ];

  function shouldWatch(filepath: string): boolean {
    if (IGNORE_PATTERNS.some((p) => filepath.includes(p))) return false;
    return CODE_EXTENSIONS.has(extname(filepath));
  }

  function startWatching(cwd: string, ctx: any): void {
    if (watcher) {
      watcher.close();
    }

    try {
      watcher = watch(cwd, { recursive: true }, (eventType, filename) => {
        if (!filename || !pairMode) return;
        const filepath = join(cwd, filename);
        if (!shouldWatch(filepath)) return;

        const now = Date.now();
        if (now - lastChangeTime < DEBOUNCE_MS) return;
        lastChangeTime = now;

        const relPath = relative(cwd, filepath);
        watchedFiles.add(relPath);

        try {
          const content = readFileSync(filepath, "utf-8");
          const lines = content.split("\n").length;
          ctx.ui.notify(
            `\u{1F4DD} File changed: ${relPath} (${lines} lines, ${eventType})\nJAE is watching in pair mode.`,
            "info",
          );
        } catch {
          ctx.ui.notify(`\u{1F4DD} File ${eventType}: ${relPath}`, "info");
        }
      });

      ctx.ui.notify(
        `\u{1F91D} Pair programming mode started!\nWatching: ${cwd}\nJAE will observe your changes and provide feedback.`,
        "info",
      );
    } catch (err) {
      ctx.ui.notify(`Failed to start file watcher: ${err}`, "error");
    }
  }

  function stopWatching(ctx: any): void {
    if (watcher) {
      watcher.close();
      watcher = null;
    }
    const filesCount = watchedFiles.size;
    watchedFiles.clear();
    ctx.ui.notify(
      `\u{1F91D} Pair programming mode stopped. ${filesCount} files were modified during session.`,
      "info",
    );
  }

  pi.on("session_end", async (_event, _ctx) => {
    if (watcher) {
      watcher.close();
      watcher = null;
      pairMode = false;
    }
  });

  pi.on("before_agent_start", async (_event, _ctx) => {
    if (pairMode && watchedFiles.size > 0) {
      const filesList = Array.from(watchedFiles).slice(0, 10).join(", ");
      return {
        systemPrompt: `\n\n# Pair Programming Mode Active\nRecently modified files: ${filesList}\nProvide constructive feedback on changes. Suggest improvements, catch bugs, and explain patterns.\n`,
      };
    }
  });

  pi.registerCommand("pair", {
    description: "Toggle pair programming mode - JAE watches and comments on your file changes",
    handler: async (_args, ctx) => {
      pairMode = !pairMode;

      if (pairMode) {
        startWatching(ctx.cwd, ctx);
        ctx.ui.setFooter("pair", "\u{1F91D} Pair Mode");
      } else {
        stopWatching(ctx);
        ctx.ui.setFooter("pair", undefined);
      }
    },
  });
}
