// engine/api-spec-generator/graphql-parser.ts — Parse GraphQL SDL strings (SPEC-286)
// ---------------------------------------------------------------------------
// Minimal SDL text parser
// ---------------------------------------------------------------------------
/** Strip comment lines from SDL */
function stripComments(sdl) {
    return sdl.replace(/#[^\n]*/g, '').trim();
}
/** Extract the inner type name, stripping [], !, wrapping */
function unwrapType(typeStr) {
    return typeStr.replace(/[[\]!]/g, '').trim();
}
/** Determine if a GraphQL type string is non-null (ends with !) */
function isRequired(typeStr) {
    const stripped = typeStr.replace(/\[.*\]/, '').trim();
    return stripped.endsWith('!');
}
/** Parse fields from inside an SDL type body: "name: Type" lines */
function parseTypeFields(body) {
    const fields = [];
    const fieldPattern = /^\s*(\w+)\s*(?:\([^)]*\))?\s*:\s*([^\s#]+)/gm;
    let match;
    while ((match = fieldPattern.exec(body)) !== null) {
        const name = match[1] ?? '';
        const typeStr = match[2] ?? '';
        if (name.length === 0 || typeStr.length === 0) {
            continue;
        }
        fields.push({
            name,
            type: unwrapType(typeStr),
            required: isRequired(typeStr),
        });
    }
    return fields;
}
/** Extract all type definitions as a map of name → fields */
function extractTypeMap(sdl) {
    const typeMap = new Map();
    const typePattern = /(?:type|input)\s+(\w+)\s*(?:implements\s+\w+\s*)?{([^}]*)}/g;
    let match;
    while ((match = typePattern.exec(sdl)) !== null) {
        const name = match[1] ?? '';
        const body = match[2] ?? '';
        if (name.length === 0) {
            continue;
        }
        typeMap.set(name, parseTypeFields(body));
    }
    return typeMap;
}
/** Extract operations from Query/Mutation/Subscription type bodies */
function extractOperations(sdl, typeMap) {
    const operations = [];
    const operationKinds = [
        'query',
        'mutation',
        'subscription',
    ];
    for (const kind of operationKinds) {
        const typeName = kind.charAt(0).toUpperCase() + kind.slice(1);
        const pattern = new RegExp(`type\\s+${typeName}\\s*{([^}]*)}`, 'i');
        const match = pattern.exec(sdl);
        if (match === null) {
            continue;
        }
        const body = match[1] ?? '';
        const opPattern = /^\s*(\w+)\s*(?:\(([^)]*)\))?\s*:\s*([^\s#\n]+)/gm;
        let opMatch;
        while ((opMatch = opPattern.exec(body)) !== null) {
            const name = opMatch[1] ?? '';
            const argsStr = opMatch[2] ?? '';
            const returnTypeStr = opMatch[3] ?? '';
            if (name.length === 0) {
                continue;
            }
            const argFields = [];
            if (argsStr.trim().length > 0) {
                const argPattern = /(\w+)\s*:\s*([^\s,)]+)/g;
                let argMatch;
                while ((argMatch = argPattern.exec(argsStr)) !== null) {
                    const argName = argMatch[1] ?? '';
                    const argType = argMatch[2] ?? '';
                    const innerType = unwrapType(argType);
                    const inputFields = typeMap.get(innerType);
                    if (inputFields !== undefined && inputFields.length > 0) {
                        argFields.push(...inputFields);
                    }
                    else {
                        argFields.push({
                            name: argName,
                            type: innerType,
                            required: isRequired(argType),
                        });
                    }
                }
            }
            operations.push({
                name,
                kind,
                fields: argFields,
                returnType: unwrapType(returnTypeStr),
                description: '',
            });
        }
    }
    return operations;
}
/** Convert a camelCase operation name to a title */
function operationTitle(name, kind) {
    const spaced = name.replace(/([A-Z])/g, ' $1').trim();
    const titled = spaced.charAt(0).toUpperCase() + spaced.slice(1);
    if (kind === 'subscription') {
        return `${titled} Subscription`;
    }
    return titled;
}
// ---------------------------------------------------------------------------
// Synthetic response info for GraphQL
// ---------------------------------------------------------------------------
function syntheticResponses() {
    return [
        { statusCode: 200, description: 'Successful response with data payload' },
        { statusCode: 200, description: 'Partial error: data with errors array' },
    ];
}
// ---------------------------------------------------------------------------
// Main parser
// ---------------------------------------------------------------------------
export function parseGraphQL(sdl) {
    if (sdl.trim().length === 0) {
        throw new Error('GraphQL SDL is empty');
    }
    const stripped = stripComments(sdl);
    const typeMap = extractTypeMap(stripped);
    const rawOperations = extractOperations(stripped, typeMap);
    if (rawOperations.length === 0) {
        throw new Error('No Query, Mutation, or Subscription types found in GraphQL SDL');
    }
    const operations = rawOperations.map((op) => {
        const title = operationTitle(op.name, op.kind);
        const resourceGroup = op.returnType.length > 0
            ? op.returnType.charAt(0).toUpperCase() + op.returnType.slice(1)
            : title;
        const fields = op.fields.map((f) => ({
            name: f.name,
            type: f.type,
            required: f.required,
            description: f.description,
        }));
        return {
            externalId: op.name,
            title,
            description: op.description ?? `GraphQL ${op.kind}: ${op.name}`,
            operationType: op.kind,
            tags: [op.kind],
            fields,
            responses: syntheticResponses(),
            resourceGroup,
        };
    });
    return {
        source: 'graphql',
        title: 'GraphQL API',
        version: '1.0.0',
        description: 'GraphQL schema operations',
        operations,
    };
}
//# sourceMappingURL=graphql-parser.js.map