# frozen_string_literal: true
module GraphQL
  class Subscriptions
    class DefaultSubscriptionResolveExtension < GraphQL::Schema::FieldExtension
      def resolve(context:, object:, arguments:)
        has_override_implementation = @field.resolver ||
          object.respond_to?(@field.resolver_method)

        if !has_override_implementation
          if context.query.subscription_update?
            object.object
          else
            context.skip
          end
        else
          yield(object, arguments)
        end
      end

      def after_resolve(value:, context:, object:, arguments:, **rest)
        if value.is_a?(GraphQL::ExecutionError)
          value
        elsif (events = context.namespace(:subscriptions)[:events])
          # This is the first execution, so gather an Event
          # for the backend to register:
          event = Subscriptions::Event.new(
            name: field.name,
            arguments: arguments_without_field_extras(arguments: arguments),
            context: context,
            field: field,
          )
          events << event
          value
        elsif context.query.subscription_topic == Subscriptions::Event.serialize(
            field.name,
            arguments_without_field_extras(arguments: arguments),
            field,
            scope: (field.subscription_scope ? context[field.subscription_scope] : nil),
          )
          # This is a subscription update. The resolver returned `skip` if it should be skipped,
          # or else it returned an object to resolve the update.
          value
        else
          # This is a subscription update, but this event wasn't triggered.
          context.skip
        end
      end

      private

      def arguments_without_field_extras(arguments:)
        arguments.dup.tap do |event_args|
          field.extras.each { |k| event_args.delete(k) }
        end
      end
    end
  end
end
