import {
  type PathTemplateSegment,
  parsePathTemplate,
} from "./path-template.js";
import type { HttpMethod } from "./types.js";

const methodNameMap: Record<HttpMethod, string> = {
  GET: "get",
  POST: "create",
  PUT: "update",
  PATCH: "patch",
  DELETE: "delete",
  HEAD: "head",
  OPTIONS: "options",
};

function toPascalCase(value: string): string {
  return value
    .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
    .split(/[^a-zA-Z0-9]+/)
    .filter(Boolean)
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join("");
}

function getMeaningfulPathSegments(path: string): PathTemplateSegment[] {
  const segments = parsePathTemplate(path).segments;

  if (
    segments[0]?.kind === "static" &&
    segments[0].value.toLowerCase() === "api"
  ) {
    return segments.slice(1);
  }

  return segments;
}

/**
 * Generate a stable contract name from an HTTP method and path.
 *
 * `/api` is ignored as a leading path segment so generated names focus on the
 * resource shape.
 */
export function generateContractName(method: HttpMethod, path: string): string {
  const methodPrefix = methodNameMap[method];
  const segments = getMeaningfulPathSegments(path);

  if (segments.length === 0) {
    return `${methodPrefix}Root`;
  }

  const nameSuffix = segments
    .map((segment) => {
      if (segment.kind === "dynamic") {
        const paramName = toPascalCase(segment.name);
        return `By${paramName || "Param"}`;
      }

      return toPascalCase(segment.value) || "Resource";
    })
    .join("");

  return `${methodPrefix}${nameSuffix}`;
}
