# frozen_string_literal: true

module Mutations
  module UserPreferences
    class Update < BaseMutation
      graphql_name 'UserPreferencesUpdate'

      authorize_granular_token permissions: :update_user_preference,
        boundary: :user,
        boundary_type: :user

      NON_NULLABLE_ARGS = [
        :extensions_marketplace_opt_in_status,
        :organization_groups_projects_display,
        :visibility_pipeline_id_type,
        :use_work_items_view,
        :merge_request_dashboard_list_type,
        :merge_request_dashboard_show_drafts,
        :wiki_use_auto_commit_message
      ].freeze

      argument :extensions_marketplace_opt_in_status, Types::ExtensionsMarketplaceOptInStatusEnum,
        required: false,
        description: 'Status of the Web IDE Extension Marketplace opt-in for the user.'
      argument :issues_sort, Types::IssueSortEnum,
        required: false,
        description: 'Sort order for issue lists.'
      argument :merge_request_dashboard_list_type, Types::MergeRequests::DashboardListTypeEnum,
        required: false,
        description: 'Merge request dashboard list rendering type.'
      argument :merge_request_dashboard_show_drafts, GraphQL::Types::Boolean,
        required: false,
        description: 'Show draft merge requests on the merge request dashboard.'
      argument :merge_requests_sort, Types::MergeRequestSortEnum,
        required: false,
        description: 'Sort order for issue lists.'
      argument :use_work_items_view, GraphQL::Types::Boolean,
        required: false,
        description: 'Use work item view instead of legacy issue view.'
      argument :visibility_pipeline_id_type, Types::VisibilityPipelineIdTypeEnum,
        required: false,
        description: 'Determines whether the pipeline list shows ID or IID.'

      argument :projects_sort, Types::Projects::ProjectSortEnum,
        required: false,
        description: 'Sort order for projects.'

      argument :organization_groups_projects_sort, Types::Organizations::GroupsProjectsSortEnum,
        required: false,
        description: 'Sort order for organization groups and projects.',
        experiment: { milestone: '17.2' }

      argument :organization_groups_projects_display, Types::Organizations::GroupsProjectsDisplayEnum,
        required: false,
        description: 'Default list view for organization groups and projects.',
        experiment: { milestone: '17.2' }

      argument :work_items_display_settings,
        type: GraphQL::Types::JSON,
        description: 'Display settings for the work item lists, e.g.: "{ shouldOpenItemsInSidePanel: false }".',
        required: false,
        experiment: { milestone: '18.1' }

      argument :orbit_settings,
        type: GraphQL::Types::JSON,
        description: 'Orbit agent settings, e.g.: "{ enabled: false }".',
        required: false,
        experiment: { milestone: '19.0' }

      argument :wiki_use_auto_commit_message,
        GraphQL::Types::Boolean,
        required: false,
        description: 'Whether to skip the commit message modal and use the auto-generated commit message when saving ' \
          'changes to a wiki document.',
        experiment: { milestone: '18.10' }

      field :user_preferences,
        Types::UserPreferencesType,
        null: true,
        description: 'User preferences after mutation.'

      def resolve(**attributes)
        attributes.delete_if { |key, value| NON_NULLABLE_ARGS.include?(key) && value.nil? }

        if attributes.include?(:extensions_marketplace_opt_in_status)
          attributes[:extensions_marketplace_opt_in_url] =
            ::WebIde::ExtensionMarketplace.marketplace_home_url(user: current_user)
        end

        user_preferences = current_user.user_preference
        if attributes[:work_items_display_settings].present?
          existing_settings = user_preferences.work_items_display_settings
          attributes[:work_items_display_settings] =
            existing_settings.merge(attributes[:work_items_display_settings])
        end

        if attributes[:orbit_settings].present?
          existing_orbit = user_preferences.orbit_settings
          attributes[:orbit_settings] = existing_orbit.merge(attributes[:orbit_settings])
        end

        user_preferences.update(attributes)

        {
          user_preferences: user_preferences.valid? ? user_preferences : nil,
          errors: errors_on_object(user_preferences)
        }
      end
    end
  end
end

Mutations::UserPreferences::Update.prepend_mod
