# frozen_string_literal: true

require_relative '../../qa_helpers'

module RuboCop
  module Cop
    module QA
      # This cop checks for the usages of API fabrications and suggests using
      # the corresponding QA factories instead.
      # @example
      #   Good:
      #     create(:project)
      #   Bad:
      #     Resource::Project.fabricate_via_api!
      # @example
      #   Good:
      #     create(:group)
      #   Bad:
      #     Resource::Group.fabricate_via_api!
      # @example
      #   Good:
      #     create(:user, username: 'username', password: 'password')
      #   Bad:
      #     Resource::User.fabricate_via_api! do |user|
      #       user.username = 'username'
      #       user.password = 'password'
      #     end
      class FabricateUsage < RuboCop::Cop::Base
        MESSAGE = "Prefer create(:%{factory}[, ...]) here."
        RESOURCES_TO_CHECK = {
          'Resource::CiVariable' => :ci_variable,
          'Resource::Commit' => :commit,
          'Resource::Design' => :design,
          'Resource::File' => :file,
          'Resource::Group' => :group,
          'Resource::GroupAccessToken' => :group_access_token,
          'Resource::GroupDeployToken' => :group_deploy_token,
          'Resource::GroupLabel' => :group_label,
          'Resource::GroupMilestone' => :group_milestone,
          'Resource::GroupRunner' => :group_runner,
          'Resource::GroupWikiPage' => :group_wiki_page,
          'Resource::Issue' => :issue,
          'Resource::Job' => :job,
          'Resource::MergeRequest' => :merge_request,
          'Resource::Package' => :package,
          'Resource::Pipeline' => :pipeline,
          'Resource::PipelineSchedule' => :pipeline_schedule,
          'Resource::Project' => :project,
          'Resource::ProjectAccessToken' => :project_access_token,
          'Resource::ProjectDeployToken' => :project_deploy_token,
          'Resource::ProjectLabel' => :project_label,
          'Resource::ProjectMilestone' => :project_milestone,
          'Resource::ProjectRunner' => :project_runner,
          'Resource::ProjectSnippet' => :project_snippet,
          'Resource::ProjectWikiPage' => :project_wiki_page,
          'Resource::Sandbox' => :sandbox,
          'Resource::Snippet' => :snippet,
          'Resource::Tag' => :tag,
          'Resource::User' => :user
        }.freeze

        RESTRICT_ON_SEND = %i[fabricate_via_api!].freeze

        # @!method const_receiver(node)
        def_node_matcher :const_receiver, <<~PATTERN
          (send $const ...)
        PATTERN

        def on_send(node)
          factory = RESOURCES_TO_CHECK[const_receiver(node)&.const_name]
          return unless factory

          add_offense(node, message: format(MESSAGE, factory: factory))
        end
      end
    end
  end
end
