import { Kind, parse } from '@0no-co/graphql.web';
// TODO consider moving this to @takeshape/graphql
export function getVariablesSchema(runtimeSchema, queryStr) {
    const doc = parse(queryStr);
    const op = doc.definitions.find((def) => def.kind === 'OperationDefinition');
    return op?.variableDefinitions && variablesToPropertySchema(runtimeSchema, op.variableDefinitions);
}
function variablesToPropertySchema(runtimeSchema, nodes) {
    const properties = {};
    const required = [];
    let argsAreFromShape = false;
    for (const node of nodes) {
        let typeNode = node.type;
        let isRequired = false;
        if (typeNode.kind === Kind.NON_NULL_TYPE) {
            isRequired = true;
            typeNode = typeNode.type;
        }
        const { propertySchema, isFromShape } = graphqlTypeNodeToPropertySchemaWithShapeInfo(runtimeSchema, typeNode);
        if (propertySchema) {
            const name = node.variable.name.value;
            properties[name] = propertySchema;
            if (isRequired) {
                required.push(name);
            }
            if (isFromShape) {
                argsAreFromShape = true;
            }
        }
    }
    return { argsSchema: { type: 'object', properties, required }, argsAreFromShape };
}
const scalarTypeMap = {
    String: 'string',
    Int: 'integer',
    Float: 'number',
    Boolean: 'boolean',
    ID: 'string',
    JSON: 'object',
    JSONObject: 'object'
};
function graphqlTypeNodeToPropertySchema(runtimeSchema, node) {
    const { propertySchema } = graphqlTypeNodeToPropertySchemaWithShapeInfo(runtimeSchema, node);
    return propertySchema;
}
function graphqlTypeNodeToPropertySchemaWithShapeInfo(runtimeSchema, node) {
    // Handle NonNullType (e.g., String!)
    if (node.kind === Kind.NON_NULL_TYPE) {
        return graphqlTypeNodeToPropertySchemaWithShapeInfo(runtimeSchema, node.type);
    }
    // Handle ListType (e.g., [String])
    if (node.kind === Kind.LIST_TYPE) {
        const { propertySchema, isFromShape } = graphqlTypeNodeToPropertySchemaWithShapeInfo(runtimeSchema, node.type);
        return {
            propertySchema: propertySchema
                ? {
                    type: 'array',
                    items: propertySchema
                }
                : undefined,
            isFromShape
        };
    }
    const typeName = node.name.value;
    const jsonType = scalarTypeMap[typeName];
    if (jsonType) {
        return { propertySchema: { type: jsonType }, isFromShape: false };
    }
    // TODO this lookup needs to account for Input suffixes and inline object shapes
    const shape = runtimeSchema.getShape(typeName);
    if (shape) {
        return { propertySchema: { '@ref': shape.ref }, isFromShape: true };
    }
    return { propertySchema: undefined, isFromShape: false };
}
