/**
 * OpenAPI Importer
 * 
 * Main entry point for importing OpenAPI specifications
 * Ported from Hoppscotch's openapi/index.ts
 */ import yaml from 'js-yaml';
import { objectHasProperty } from '../../utils';
import { validateOpenAPISpec } from './validator';
import { dereferenceOpenAPISpec, hasUnresolvedRefs } from './dereferencer';
import { convertOpenAPIToCollection } from './transformer';
export const OPENAPI_DEREF_ERROR = 'openapi/deref_error';
export const IMPORTER_INVALID_FILE_FORMAT = 'importer/invalid_file_format';
/**
 * Safely parses JSON string
 */ function safeParseJSON(str) {
    try {
        return JSON.parse(str);
    } catch  {
        return null;
    }
}
/**
 * Safely parses YAML string
 */ function safeParseYAML(str) {
    try {
        return yaml.load(str);
    } catch  {
        return null;
    }
}
/**
 * Parses OpenAPI document content (JSON or YAML)
 */ function parseOpenAPIDocContent(str) {
    const jsonResult = safeParseJSON(str);
    if (jsonResult !== null) {
        return jsonResult;
    }
    return safeParseYAML(str);
}
/**
 * Checks if document is OpenAPI v2
 */ function isOpenAPIV2Document(doc) {
    return objectHasProperty(doc, 'swagger') && typeof doc.swagger === 'string' && doc.swagger === '2.0';
}
/**
 * Checks if document is OpenAPI v3
 */ function isOpenAPIV3Document(doc) {
    return objectHasProperty(doc, 'openapi') && typeof doc.openapi === 'string' && doc.openapi.startsWith('3.');
}
/**
 * Imports OpenAPI specification from file contents or document
 * 
 * @param input - OpenAPI document object or array of file contents (strings)
 * @returns Promise resolving to BrainfishCollection array
 */ export async function importOpenAPISpec(input) {
    let docArr;
    // Handle different input types
    if (typeof input === 'string') {
        // Single file content string
        const parsed = parseOpenAPIDocContent(input);
        if (!parsed) {
            throw new Error(IMPORTER_INVALID_FILE_FORMAT);
        }
        docArr = [
            parsed
        ];
    } else if (Array.isArray(input)) {
        // Array of file content strings
        docArr = input.map((str)=>parseOpenAPIDocContent(str)).filter((doc)=>doc !== null);
        if (docArr.length === 0) {
            throw new Error(IMPORTER_INVALID_FILE_FORMAT);
        }
    } else {
        // Already a parsed OpenAPI document
        docArr = [
            input
        ];
    }
    // Validate documents
    const validatedDocs = [];
    for (const docObj of docArr){
        try {
            // More lenient check - if it has paths, we'll try to import it
            const isValidOpenAPISpec = objectHasProperty(docObj, 'paths') && (isOpenAPIV2Document(docObj) || isOpenAPIV3Document(docObj) || objectHasProperty(docObj, 'info'));
            if (!isValidOpenAPISpec) {
                throw new Error('INVALID_OPENAPI_SPEC');
            }
            try {
                const validatedDoc = await validateOpenAPISpec(docObj);
                validatedDocs.push(validatedDoc);
            } catch (validationError) {
                // If validation fails but it has basic OpenAPI structure, add it anyway
                if (objectHasProperty(docObj, 'paths')) {
                    validatedDocs.push(docObj);
                } else {
                    throw validationError;
                }
            }
        } catch (err) {
            if (err instanceof Error && err.message === 'INVALID_OPENAPI_SPEC') {
                throw new Error('INVALID_OPENAPI_SPEC');
            }
            // Continue with other documents
            console.warn('Failed to validate document:', err);
        }
    }
    if (validatedDocs.length === 0) {
        throw new Error(IMPORTER_INVALID_FILE_FORMAT);
    }
    // Dereference documents
    const dereferencedDocs = [];
    for (const docObj of validatedDocs){
        try {
            const dereferencedDoc = await dereferenceOpenAPISpec(docObj);
            dereferencedDocs.push(dereferencedDoc);
        } catch  {
            // Check if the document has unresolved references
            if (hasUnresolvedRefs(docObj)) {
                console.warn('Document contains unresolved references which may affect import quality');
            }
            // If dereferencing fails, use the original document
            dereferencedDocs.push(docObj);
        }
    }
    // Convert to BrainfishCollections
    return convertOpenAPIToCollection(dereferencedDocs);
}
