module Gitlab
  module ImportExport
    class MembersMapper

      attr_reader :note_member_list

      def initialize(exported_members:, user:, project:)
        @exported_members = exported_members
        @user = user
        @project = project
        @note_member_list = []

        # This needs to run first, as second call would be from generate_map
        # which means project members already exist.
        ensure_default_member!
      end

      def map
        @map ||= generate_map
      end

      def default_user_id
        @user.id
      end

      private


      def generate_map
        @map ||=
          begin
            @exported_members.inject(missing_keys_tracking_hash) do |hash, member|
              existing_user = User.where(find_project_user_query(member)).first
              old_user_id = member['user']['id']
              if existing_user && add_user_as_team_member(existing_user, member).persisted?
                hash[old_user_id] = existing_user.id
              end
              hash
            end
          end
      end

      def missing_keys_tracking_hash
        Hash.new do |_, key|
          @note_member_list << key
          @user.id
        end
      end

      def ensure_default_member!
        ProjectMember.create!(user: @user, access_level: ProjectMember::MASTER, source_id: @project.id, importing: true)
      end

      def add_user_as_team_member(existing_user, member)
        member['user'] = existing_user

        ProjectMember.create(member_hash(member))
      end

      def member_hash(member)
        member.except('id').merge(source_id: @project.id, importing: true)
      end

      def find_project_user_query(member)
        user_arel[:username].eq(member['user']['username']).or(user_arel[:email].eq(member['user']['email']))
      end

      def user_arel
        @user_arel ||= User.arel_table
      end
    end
  end
end