import path from "node:path";

function escapeRegExp(value: string): string {
  return value.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
}

function normalizeForMatch(value: string): string {
  return value.replace(/\\/g, "/");
}

function globToRegExp(glob: string): RegExp {
  const normalized = normalizeForMatch(glob);
  let pattern = "^";

  for (let index = 0; index < normalized.length; index += 1) {
    const char = normalized[index];
    const next = normalized[index + 1];

    if (char === "*" && next === "*") {
      pattern += ".*";
      index += 1;
      continue;
    }

    if (char === "*") {
      pattern += "[^/]*";
      continue;
    }

    if (char === "?") {
      pattern += "[^/]";
      continue;
    }

    if (char === "/") {
      pattern += "/";
      continue;
    }

    pattern += escapeRegExp(char);
  }

  pattern += "$";
  return new RegExp(pattern, process.platform === "win32" ? "i" : "");
}

export function toPosixPath(value: string): string {
  return normalizeForMatch(value);
}

export function basenameForMatch(value: string): string {
  return path.basename(value);
}

export function matchesGlob(value: string, glob: string): boolean {
  return globToRegExp(glob).test(normalizeForMatch(value));
}

export function matchesAnyGlob(value: string, globs: string[]): boolean {
  if (!Array.isArray(globs) || globs.length === 0) {
    return false;
  }

  const normalizedValue = normalizeForMatch(value);
  const basename = basenameForMatch(normalizedValue);
  return globs.some((glob) => {
    if (typeof glob !== "string" || glob.trim() === "") {
      return false;
    }
    const trimmed = glob.trim();
    return matchesGlob(normalizedValue, trimmed) || matchesGlob(basename, trimmed);
  });
}
