import { getTextInput, type ToolInput } from "../../core/io/input-types";
import type { ToolResult } from "../../core/io/output-types";
import type { ToolContext } from "../../core/plugins/plugin-types";
import type { RegexTesterOptions } from "./index";

export async function runRegexTester(
  input: ToolInput,
  options: RegexTesterOptions,
  context?: ToolContext
): Promise<ToolResult> {
  void context;

  let pattern = getTextInput(input, "pattern");
  let testText = getTextInput(input, "text");

  // Fallback to legacy single text parsing (for backwards compatibility / unit tests)
  if ((!pattern || !testText) && input.text) {
    const text = input.text;
    const firstLine = text.indexOf("\n") >= 0 ? text.substring(0, text.indexOf("\n")).trim() : text.trim();
    const rest = text.indexOf("\n") >= 0 ? text.substring(text.indexOf("\n") + 1) : "";
    pattern = pattern || firstLine;
    testText = testText || rest;
  }

  if (!pattern) {
    throw new Error("Enter a regex pattern.");
  }

  if (pattern.startsWith("/") && pattern.lastIndexOf("/") > 0) {
    const lastSlash = pattern.lastIndexOf("/");
    const inlineFlags = pattern.substring(lastSlash + 1);
    pattern = pattern.substring(1, lastSlash);
    if (!options.flags) {
      (options as unknown as Record<string, string>).flags = inlineFlags;
    }
  }

  const flags = options.flags || "gi";

  let regex: RegExp;
  try {
    regex = new RegExp(pattern, flags);
  } catch (cause) {
    const msg = cause instanceof Error ? cause.message : String(cause);
    throw new Error(`Invalid regex: ${msg}`, { cause });
  }

  if (!testText) {
    return {
      type: "json",
      value: {
        pattern,
        flags,
        matches: [],
        matchCount: 0,
        groups: [],
      },
    };
  }

  const matches: Array<{ match: string; index: number; groups: Record<string, string> | null }> = [];
  let matchResult: RegExpExecArray | null;

  if (regex.global) {
    while ((matchResult = regex.exec(testText)) !== null) {
      matches.push({
        match: matchResult[0],
        index: matchResult.index,
        groups: matchResult.groups ? { ...matchResult.groups } : null,
      });
      if (matchResult[0].length === 0) {
        regex.lastIndex++;
      }
    }
  } else {
    matchResult = regex.exec(testText);
    if (matchResult) {
      matches.push({
        match: matchResult[0],
        index: matchResult.index,
        groups: matchResult.groups ? { ...matchResult.groups } : null,
      });
    }
  }

  const allGroups = new Set<string>();
  const groupRegex = /\(\?<(?<name>[a-zA-Z][a-zA-Z0-9]*)>/g;
  let groupMatch: RegExpExecArray | null;
  const tempRegex = new RegExp(groupRegex);
  while ((groupMatch = tempRegex.exec(pattern)) !== null) {
    if (groupMatch.groups?.name) {
      allGroups.add(groupMatch.groups.name);
    }
  }

  return {
    type: "json",
    value: {
      pattern,
      flags,
      matches,
      matchCount: matches.length,
      testTextLength: testText.length,
      groups: Array.from(allGroups),
    },
  };
}
