import getInlineFragment from "../shared/helpers/getInlineFragment";
import {
  FieldQuery,
  FragmentDefinitions,
  ObjectValueWithVariables,
} from "../shared/types";

export default function mergeFieldQueryAndArgs(
  fragmentDefinitions: FragmentDefinitions<ObjectValueWithVariables>,
  query: FieldQuery<ObjectValueWithVariables> | null,
  queryArgs: ObjectValueWithVariables | null,
  unwrapObjectArgs = false
): FieldQuery<ObjectValueWithVariables> | null {
  if (!query) {
    return null;
  }
  return Object.fromEntries(
    Object.entries(query).map(([objectTypeName, fragment]) => {
      const objectArgs = unwrapObjectArgs
        ? queryArgs &&
          queryArgs[objectTypeName] &&
          queryArgs[objectTypeName] instanceof Object
          ? (queryArgs[objectTypeName] as ObjectValueWithVariables)
          : null
        : queryArgs;

      const inlineFragment = getInlineFragment(fragmentDefinitions, fragment);

      return [
        objectTypeName,
        {
          type: "InlineFragment",
          objectTypeName,
          selection: Object.fromEntries(
            Object.entries(inlineFragment.selection).map(
              ([fieldName, { fieldQuery }]) => {
                const fieldArgs =
                  objectArgs &&
                  objectArgs[fieldName] &&
                  objectArgs[fieldName] instanceof Object
                    ? (objectArgs[fieldName] as ObjectValueWithVariables)
                    : null;

                return [
                  fieldName,
                  {
                    fieldArguments: {
                      ...(fieldArgs && fieldArgs.args
                        ? (fieldArgs.args as ObjectValueWithVariables)
                        : {}),
                    },
                    fieldQuery: fieldQuery
                      ? mergeFieldQueryAndArgs(
                          fragmentDefinitions,
                          fieldQuery,
                          fieldArgs,
                          true
                        )
                      : null,
                  },
                ];
              }
            )
          ),
        },
      ];
    })
  );
}
