/**
 * MIRROR of main frontend `frontend/src/lib/isPathAllowed.ts` — keep in sync
 * manually. Rationale: tradein-mvp — отдельный Next.js bundle с basePath=/trade-in,
 * нет общего workspace package, поэтому дублируем (как делают backend mirrors
 * `backend/app/core/auth.py` ↔ `tradein-mvp/backend/app/core/auth.py`).
 *
 * JS-порт `backend/app/core/auth.py::is_path_allowed`. Семантика glob:
 *   `/**`        → matches everything (admin scope)
 *   `/foo/**`    → matches `/foo`, `/foo/`, `/foo/bar`, …
 *   `/foo/*`     → один сегмент после `/foo/`
 *   `/foo`       → exact match
 */

const REGEX_META = /[.+^${}()|[\]\\]/g;

function escapeRegex(s: string): string {
  return s.replace(REGEX_META, "\\$&");
}

function globToRegex(pattern: string): RegExp {
  const dstar = "\x00DSTAR\x00";
  const sstar = "\x00SSTAR\x00";

  const work = pattern.replace(/\*\*/g, dstar).replace(/\*/g, sstar);
  let regex = escapeRegex(work);
  regex = regex.replace(new RegExp(escapeRegex(dstar), "g"), ".*");
  regex = regex.replace(new RegExp(escapeRegex(sstar), "g"), "[^/]*");

  if (regex.endsWith("/.*")) {
    regex = regex.slice(0, -"/.*".length) + "(?:/.*)?";
  }
  return new RegExp(`^${regex}$`);
}

const REGEX_CACHE = new Map<string, RegExp>();

function compileGlob(pattern: string): RegExp {
  const cached = REGEX_CACHE.get(pattern);
  if (cached) return cached;
  const compiled = globToRegex(pattern);
  REGEX_CACHE.set(pattern, compiled);
  return compiled;
}

export function isPathAllowed(
  allowedPaths: readonly string[],
  denyPaths: readonly string[],
  path: string,
): boolean {
  for (const p of denyPaths) {
    if (compileGlob(p).test(path)) return false;
  }
  for (const p of allowedPaths) {
    if (compileGlob(p).test(path)) return true;
  }
  return false;
}
