import { buildOpenApiDocument } from "@open-mercato/shared/lib/openapi";
import { fetchWithTimeout, resolveTimeoutMs } from "@open-mercato/shared/lib/http/fetchWithTimeout";
const DEFAULT_OPENAPI_FETCH_TIMEOUT_MS = 1e4;
function resolveOpenapiFetchTimeoutMs() {
  const raw = process.env.AI_OPENAPI_FETCH_TIMEOUT_MS;
  const parsed = raw ? Number.parseInt(raw, 10) : void 0;
  return resolveTimeoutMs(parsed, DEFAULT_OPENAPI_FETCH_TIMEOUT_MS);
}
let endpointsCache = null;
let endpointsByOperationId = null;
let rawSpecCache = null;
async function getApiEndpoints() {
  if (endpointsCache) {
    return endpointsCache;
  }
  endpointsCache = await parseApiEndpoints();
  endpointsByOperationId = new Map(endpointsCache.map((e) => [e.operationId, e]));
  return endpointsCache;
}
async function getEndpointByOperationId(operationId) {
  await getApiEndpoints();
  return endpointsByOperationId?.get(operationId) ?? null;
}
async function getRawOpenApiSpec() {
  if (rawSpecCache) return rawSpecCache;
  rawSpecCache = await loadRawOpenApiSpec();
  return rawSpecCache;
}
function setRawSpecCache(doc) {
  rawSpecCache = doc;
}
function clearRawSpecCache() {
  rawSpecCache = null;
}
async function loadRichOpenApiSpec() {
  if (rawSpecCache) return rawSpecCache;
  try {
    const { getModules } = await import("@open-mercato/shared/lib/modules/registry");
    const modules = getModules();
    const modulesWithApis = modules.filter((m) => m.apis && m.apis.length > 0);
    if (modulesWithApis.length > 0) {
      const doc = buildOpenApiDocument(modules, {
        title: "Open Mercato API",
        version: "1.0.0",
        servers: [{ url: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000" }]
      });
      if (!doc.paths || Object.keys(doc.paths).length === 0) {
        return null;
      }
      console.error(`[API Index] Rich OpenAPI spec built from ${modulesWithApis.length} modules (Tier 2)`);
      rawSpecCache = doc;
      return doc;
    }
  } catch {
  }
  rawSpecCache = await loadRawOpenApiSpec();
  return rawSpecCache;
}
async function loadRawOpenApiSpec() {
  try {
    const fs = await import("node:fs");
    const path = await import("node:path");
    const { findAppRoot, findAllApps } = await import("@open-mercato/shared/lib/bootstrap/appResolver");
    let appRoot = findAppRoot();
    if (!appRoot) {
      let current = process.cwd();
      while (current !== path.dirname(current)) {
        const appsDir = path.join(current, "apps");
        if (fs.existsSync(appsDir)) {
          const apps = findAllApps(current);
          if (apps.length > 0) {
            appRoot = apps[0];
            break;
          }
        }
        current = path.dirname(current);
      }
    }
    if (appRoot) {
      const jsonPath = path.join(appRoot.generatedDir, "openapi.generated.json");
      if (fs.existsSync(jsonPath)) {
        const doc = JSON.parse(fs.readFileSync(jsonPath, "utf-8"));
        console.error(`[API Index] Raw OpenAPI spec loaded from ${jsonPath}`);
        return doc;
      }
    }
  } catch (error) {
    console.error("[API Index] Raw spec from JSON failed:", error instanceof Error ? error.message : error);
  }
  try {
    const { getModules } = await import("@open-mercato/shared/lib/modules/registry");
    const modules = getModules();
    const modulesWithApis = modules.filter((m) => m.apis && m.apis.length > 0);
    if (modulesWithApis.length > 0) {
      const doc = buildOpenApiDocument(modules, {
        title: "Open Mercato API",
        version: "1.0.0",
        servers: [{ url: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000" }]
      });
      console.error(`[API Index] Raw OpenAPI spec built from ${modulesWithApis.length} modules`);
      return doc;
    }
  } catch {
  }
  const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || process.env.NEXT_PUBLIC_APP_URL || process.env.APP_URL || "http://localhost:3000";
  try {
    const response = await fetchWithTimeout(`${baseUrl}/api/docs/openapi`, {
      timeoutMs: resolveOpenapiFetchTimeoutMs()
    });
    if (response.ok) {
      const doc = await response.json();
      console.error("[API Index] Raw OpenAPI spec fetched via HTTP");
      return doc;
    }
  } catch (error) {
    console.error("[API Index] Raw spec HTTP fetch failed:", error instanceof Error ? error.message : error);
  }
  return null;
}
async function parseApiEndpointsFromGeneratedJson() {
  try {
    const fs = await import("node:fs");
    const path = await import("node:path");
    const { findAppRoot, findAllApps } = await import("@open-mercato/shared/lib/bootstrap/appResolver");
    let appRoot = findAppRoot();
    if (!appRoot) {
      let current = process.cwd();
      while (current !== path.dirname(current)) {
        const appsDir = path.join(current, "apps");
        if (fs.existsSync(appsDir)) {
          const apps = findAllApps(current);
          if (apps.length > 0) {
            appRoot = apps[0];
            break;
          }
        }
        current = path.dirname(current);
      }
    }
    if (!appRoot) {
      console.error("[API Index] Could not find app root");
      return [];
    }
    const jsonPath = path.join(appRoot.generatedDir, "openapi.generated.json");
    if (!fs.existsSync(jsonPath)) {
      console.error("[API Index] openapi.generated.json not found - run yarn generate");
      return [];
    }
    const doc = JSON.parse(fs.readFileSync(jsonPath, "utf-8"));
    console.error(`[API Index] Loaded OpenAPI from ${jsonPath}`);
    return extractEndpoints(doc);
  } catch (error) {
    console.error("[API Index] Error reading generated JSON:", error instanceof Error ? error.message : error);
    return [];
  }
}
async function parseApiEndpointsFromModules() {
  try {
    const { getModules } = await import("@open-mercato/shared/lib/modules/registry");
    const modules = getModules();
    const modulesWithApis = modules.filter((m) => m.apis && m.apis.length > 0);
    if (modulesWithApis.length > 0) {
      console.error(
        `[API Index] Found ${modules.length} modules, ${modulesWithApis.length} with APIs`
      );
      const doc = buildOpenApiDocument(modules, {
        title: "Open Mercato API",
        version: "1.0.0",
        servers: [{ url: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000" }]
      });
      if (!doc.paths || Object.keys(doc.paths).length === 0) {
        return [];
      }
      return extractEndpoints(doc);
    }
  } catch {
  }
  return [];
}
async function parseApiEndpointsFromHttp() {
  const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || process.env.NEXT_PUBLIC_APP_URL || process.env.APP_URL || "http://localhost:3000";
  const openApiUrl = `${baseUrl}/api/docs/openapi`;
  try {
    console.error(`[API Index] Fetching OpenAPI spec from ${openApiUrl}...`);
    const response = await fetchWithTimeout(openApiUrl, {
      timeoutMs: resolveOpenapiFetchTimeoutMs()
    });
    if (!response.ok) {
      console.error(`[API Index] Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`);
      return [];
    }
    const doc = await response.json();
    console.error(`[API Index] Successfully fetched OpenAPI spec`);
    return extractEndpoints(doc);
  } catch (error) {
    console.error("[API Index] Could not fetch OpenAPI spec:", error instanceof Error ? error.message : error);
    console.error("[API Index] Make sure the app is running at", baseUrl);
    return [];
  }
}
async function parseApiEndpoints() {
  const fromJson = await parseApiEndpointsFromGeneratedJson();
  if (fromJson.length > 0) {
    console.error(`[API Index] Loaded ${fromJson.length} endpoints from generated JSON`);
    return fromJson;
  }
  const fromModules = await parseApiEndpointsFromModules();
  if (fromModules.length > 0) {
    console.error(`[API Index] Loaded ${fromModules.length} endpoints from modules registry`);
    return fromModules;
  }
  console.error("[API Index] Generated JSON and modules not available, falling back to HTTP fetch...");
  return parseApiEndpointsFromHttp();
}
function extractEndpoints(doc) {
  const endpoints = [];
  const validMethods = ["get", "post", "put", "patch", "delete"];
  if (!doc.paths) {
    return endpoints;
  }
  for (const [path, pathItem] of Object.entries(doc.paths)) {
    if (!pathItem || typeof pathItem !== "object") continue;
    for (const [method, operation] of Object.entries(pathItem)) {
      if (!validMethods.includes(method.toLowerCase())) continue;
      if (!operation || typeof operation !== "object") continue;
      const op = operation;
      const operationId = op.operationId || generateOperationId(path, method);
      const endpoint = {
        id: operationId,
        operationId,
        method: method.toUpperCase(),
        path,
        summary: op.summary || "",
        description: op.description || op.summary || `${method.toUpperCase()} ${path}`,
        tags: op.tags || [],
        requiredFeatures: op["x-require-features"] || [],
        deprecated: op.deprecated || false,
        parameters: extractParameters(op.parameters || []),
        requestBodySchema: extractRequestBodySchema(op.requestBody, doc.components?.schemas)
      };
      endpoints.push(endpoint);
    }
  }
  console.error(`[API Index] Parsed ${endpoints.length} endpoints from OpenAPI spec`);
  return endpoints;
}
function generateOperationId(path, method) {
  const pathParts = path.replace(/^\//, "").replace(/\{([^}]+)\}/g, "by_$1").split("/").filter(Boolean).join("_");
  return `${method.toLowerCase()}_${pathParts}`;
}
function extractParameters(params) {
  return params.filter((p) => p.in === "path" || p.in === "query").map((p) => ({
    name: p.name,
    in: p.in,
    required: p.required ?? false,
    type: p.schema?.type || "string",
    description: p.description || ""
  }));
}
function extractRequestBodySchema(requestBody, schemas) {
  if (!requestBody?.content?.["application/json"]?.schema) {
    return null;
  }
  const schema = requestBody.content["application/json"].schema;
  if (schema.$ref && schemas) {
    const refPath = schema.$ref.replace("#/components/schemas/", "");
    return schemas[refPath] || schema;
  }
  return schema;
}
function clearEndpointCache() {
  endpointsCache = null;
  endpointsByOperationId = null;
  rawSpecCache = null;
}
function simplifyRequestBodySchema(schema) {
  if (!schema) return null;
  const properties = {};
  const required = schema.required || [];
  const schemaProps = schema.properties || schema;
  for (const [key, value] of Object.entries(schemaProps)) {
    if (typeof value !== "object" || value === null) continue;
    const propSchema = value;
    const prop = {
      type: propSchema.type || "unknown"
    };
    if (propSchema.format) prop.format = propSchema.format;
    if (propSchema.enum && Array.isArray(propSchema.enum)) {
      prop.enum = propSchema.enum.slice(0, 10);
    }
    properties[key] = prop;
  }
  return { required, properties };
}
export {
  clearEndpointCache,
  clearRawSpecCache,
  getApiEndpoints,
  getEndpointByOperationId,
  getRawOpenApiSpec,
  loadRichOpenApiSpec,
  setRawSpecCache,
  simplifyRequestBodySchema
};
//# sourceMappingURL=api-endpoint-index.js.map
