/**
 * OpenAPI Dereferencer
 * 
 * Ported from Hoppscotch's openapi-import-worker.ts
 * Converts Web Worker pattern to direct function calls for Next.js
 */

import SwaggerParser from '@apidevtools/swagger-parser'
import type { OpenAPI } from 'openapi-types'

/**
 * Dereferences all $ref references in an OpenAPI document
 * 
 * @param docs - The OpenAPI document to dereference
 * @returns Promise resolving to dereferenced OpenAPI document
 * @throws Error if dereferencing fails
 */
export async function dereferenceOpenAPISpec(
  docs: OpenAPI.Document
): Promise<OpenAPI.Document> {
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const dereferenced = await SwaggerParser.dereference(docs as any)
    return dereferenced as OpenAPI.Document
  } catch {
    throw new Error('COULD_NOT_DEREFERENCE')
  }
}

/**
 * Checks if a document has unresolved $ref references
 * 
 * @param obj - The object to check
 * @param visited - Set of visited objects to detect circular references
 * @returns true if unresolved references are found
 */
export function hasUnresolvedRefs(
  obj: unknown,
  visited = new WeakSet()
): boolean {
  // Handle non-objects or null
  if (!obj || typeof obj !== 'object') return false

  // Check for circular references
  if (visited.has(obj)) return false

  // Add current object to visited set
  visited.add(obj)

  // Check if current object has $ref property
  if ('$ref' in obj && typeof obj.$ref === 'string') return true

  // Check arrays
  if (Array.isArray(obj)) {
    return obj.some((item) => hasUnresolvedRefs(item, visited))
  }

  // Check object properties
  return Object.values(obj).some((value) => hasUnresolvedRefs(value, visited))
}
