import { parsePathTemplate } from "../contracts/index.js";

export type CompiledPath = {
  keys: string[];
  pattern: RegExp;
  segments: ReturnType<typeof parsePathTemplate>["segments"];
  normalizedPath: string;
  shapeKey: string;
};

export class PathDecodeError extends Error {
  constructor() {
    super("Malformed URL path");
    this.name = "PathDecodeError";
  }
}

export function compilePath(path: string): CompiledPath {
  const parsed = parsePathTemplate(path);
  const regexParts = parsed.segments.map((segment) =>
    segment.kind === "dynamic"
      ? "([^/]+)"
      : segment.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"),
  );
  const pattern = new RegExp(`^/${regexParts.join("/")}$`);
  return { ...parsed, pattern };
}

export function decodeMatchedParams(
  keys: string[],
  match: RegExpExecArray,
): Record<string, string> {
  const params: Record<string, string> = {};
  try {
    keys.forEach((key, index) => {
      params[key] = decodeURIComponent(match[index + 1]);
    });
  } catch (error) {
    if (error instanceof URIError) {
      throw new PathDecodeError();
    }
    throw error;
  }
  return params;
}

export function compareRouteSpecificity(
  a: CompiledPath,
  b: CompiledPath,
): number {
  const maxLength = Math.max(a.segments.length, b.segments.length);
  for (let index = 0; index < maxLength; index++) {
    const aSegment = a.segments[index];
    const bSegment = b.segments[index];

    if (!aSegment) return 1;
    if (!bSegment) return -1;

    if (aSegment.kind === bSegment.kind) continue;
    return aSegment.kind === "static" ? -1 : 1;
  }

  return 0;
}
