module SupportTools
  class AegisGateway < SupportTools::Base
    self.service_endpoint = Settings.aegis.endpoint

    attributes :user_id, :audit_id

    # @!attribute

    def self.suspension_guides
      response = post '/twirp/code.justin.tv.safety.gateway.Gateway/GetSuspensionGuide', { body: {}.to_json, headers: {'Content-Type' => 'application/json'} }
      return {} unless response.success?
      return response.body
    end

    def self.create_enforcement(options)
      params = {
        content: options[:content],
        description: options[:description],
        detailed_reason: options[:detailed_reason],
        from_user_id: options[:from_user_id],
        ip_ban: options[:ip_ban],
        origin: "web/admin-panel",
        permanent: options[:permanent],
        reason: options[:reason],
        target_user_user_id: options[:target_user_user_id],
      }

      response = post '/twirp/code.justin.tv.safety.gateway.Gateway/CreateEnforcement', { body: params.to_json, headers: {'Content-Type' => 'application/json'} }
      return response.success?
    end

    def self.delete_report_clips_by_user(options)
      params = {
        user_id: options[:user_id],
        limit: options[:limit],
        cursor: options[:cursor],
      }
      response = post '/twirp/code.justin.tv.safety.gateway.Gateway/DeleteReportClipsByUserPaginated', { body: params.to_json, headers: {'Content-Type' => 'application/json'} }
      return {} unless response.success?
      return response.body
    end

    def self.report_clip_count(user_id)
      params = {
        user_id: user_id,
      }
      response = post '/twirp/code.justin.tv.safety.gateway.Gateway/GetReportClipCountByUser', { body: params.to_json, headers: {'Content-Type' => 'application/json'} }
      return {} unless response.success?
      return response.body
    end

    #
    # records a Force Username Reset audit to Safety's machine learning system via their Gateway service
    #
    # @see ADMIN-1537 Create audits for successful appeals
    #
    # @param [Symbol] action The type of action to audit; Must be one of: :appeal_successful, :username_changed
    # @param [String] login The username the reset or appeal was performed for
    # @param [String, Integer] user_id The User ID owning the actioned username
    # @param [String] ldap The LDAP ID of the Employee performing the auditable action
    #
    # @return [AegisGateway] An AegisGateway instance, containing either an audit_id or errors
    #
    def self.create_force_username_reset_audit(action:, login:, user_id:, ldap:)
      unless [:appeal_successful, :username_changed].include?(action)
        raise ArgumentError, "Parameter `action` value: `#{action}`. Expected any: :appeal_successful, :username_changed"
      end

      # relies on https://git.xarth.tv/safety/gateway/blob/4fb533ff474b0317cedc0a94644d5092385b0153/rpc/gateway/gateway.proto#L516
      # any time the above changes, this would also need to be updated
      force_username_reset_audit_action = {
        username_changed: 1,
        appeal_successful: 2
      }

      params = {
        action: force_username_reset_audit_action[action],
        user_username: login,
        user_id: user_id,
        action_by: ldap
      }

      response = post '/twirp/code.justin.tv.safety.gateway.Gateway/CreateForceUsernameResetAudit', { body: params.to_json, headers: {'Content-Type' => 'application/json'} }

      unless response.success?
        # There could be a number of reasons a request isn't successful
        raise(Faraday::ClientError,
            {
              status: response.status,
              headers: response.headers,
              body: response.body
            })
      end
    rescue Faraday::TimeoutError => e
      Raven.capture_exception(e, extra: {json: params.to_json, body: e.try(:response).try(:[], :body), message: e.try(:message)})
      from_errors('Request to Gateway timed out')
    rescue ArgumentError => e
      Raven.capture_exception(e, extra: {json: params.to_json, body: e.try(:response).try(:[], :body), message: e.try(:message)})
      from_errors(e)
    rescue Faraday::ClientError => e
      Raven.capture_exception(e, extra: {json: params.to_json, body: e.try(:response).try(:[], :body), message: e.try(:message)})
      from_errors("Unknown error: #{e}")
    else
      ### We should be good!
      from_attributes(
        {
          user_id: user_id
        }.merge({
          audit_id: response.body.try(:[], :id)
        })
      )
    end
  end
end
