# SPDX-FileCopyrightText: 2020 Zach Daniel
#
# SPDX-License-Identifier: MIT

defmodule AshGraphql.Graphql.IdTranslator do
  @moduledoc false

  def translate_relay_ids(%{state: :unresolved} = resolution, relay_id_translations) do
    arguments =
      Enum.reduce(relay_id_translations, resolution.arguments, &process/2)

    %{resolution | arguments: arguments}
  end

  def translate_relay_ids(resolution, _relay_id_translations) do
    resolution
  end

  defp process({field, nested_translations}, args) when is_list(nested_translations) do
    case Map.get(args, field) do
      subtree when is_map(subtree) ->
        new_subtree = Enum.reduce(nested_translations, subtree, &process/2)
        Map.put(args, field, new_subtree)

      elements when is_list(elements) ->
        new_elements =
          Enum.map(elements, fn element ->
            Enum.reduce(nested_translations, element, &process/2)
          end)

        Map.put(args, field, new_elements)

      _ ->
        args
    end
  end

  defp process({field, type}, args) when is_atom(type) do
    case Map.get(args, field) do
      id when is_binary(id) ->
        case AshGraphql.Resource.decode_relay_id(id) do
          {:ok, %{type: ^type, id: decoded_id}} ->
            Map.put(args, field, decoded_id)

          _ ->
            # If we fail to decode for the correct type, we just skip translation
            # This will be marked as an invalid input down the line
            args
        end

      [id | _] = ids when is_binary(id) ->
        decoded_ids =
          Enum.map(ids, fn id ->
            case AshGraphql.Resource.decode_relay_id(id) do
              {:ok, %{type: ^type, id: decoded_id}} ->
                decoded_id

              _ ->
                # If we fail to decode for the correct type, we just skip translation
                # This will be marked as an invalid input down the line
                id
            end
          end)

        Map.put(args, field, decoded_ids)

      _ ->
        args
    end
  end
end
