module Passport
  class TwoFactor < Passport::Base

    attributes :user_id, :authy_id, :last_four_digits, :country_code, :region_code, :created_at, :updated_at, :disabled_at
    self.primary_attribute = :user_id

    def self.get_2fa(user_id:)
      response = get "/users/#{user_id}/2fa/info"
      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
    ### Error states defined at
    ### https://git.xarth.tv/identity/passport/blob/4b60c5b258f97b30b5707ef2b3bffeea276bb926/doc/api/json_api/2fa_info.md#errors
    rescue Faraday::TimeoutError
      from_errors([ERR_TIMEOUT])
    rescue Faraday::ResourceNotFound, Faraday::MissingDependency, Faraday::ClientError => e
      error_state =
        case e.try(:response).try(:[], :status)
        when 424
          [ERR_FROM_AUTHY, e.try(:response).try(:[], :body)]
        when 404
          [ERR_MFA_NOT_ENABLED, e.try(:response).try(:[], :body)]
        when 500
          [ERR_FROM_PASSPORT, e.try(:response).try(:[], :body)]
        else
          [ERR_UNKNOWN, e.message]
        end
      from_errors(error_state)
    else
      ### We should be good!
      from_attributes({user_id: user_id}.merge(response.body))
    end

    def self.get_passport_2fa(user_id:)
      response = get "/users/#{user_id}/2fa"
      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
      from_errors([ERR_TIMEOUT])
    rescue Faraday::ResourceNotFound, Faraday::MissingDependency, Faraday::ClientError => e
      ### Status codes
      ### * 200 2fa enabled for user in passport db
      ### * 500 server error (error from passport db)
      ### * 404 user doesn't have 2fa
      error_state =
        case e.try(:response).try(:[], :status)
        when 404
          [ERR_MFA_NOT_ENABLED, e.try(:response).try(:[], :body)]
        when 500
          [ERR_FROM_PASSPORT, e.try(:response).try(:[], :body)]
        else
          [ERR_UNKNOWN, e.message]
        end
      from_errors(error_state)
    else
      ### We should be good!
      from_attributes({user_id: user_id}.merge(response.body))
    end

    def self.disable_2fa(user_id:)
      response = delete "/users/#{user_id}/2fa/disable"
      unless response.success?
        raise(Faraday::ClientError,
            {
              status: response.status,
              headers: response.headers,
              body: response.body
            })
      end
    rescue Faraday::TimeoutError
      from_errors([ERR_TIMEOUT])
    rescue Faraday::ResourceNotFound, Faraday::MissingDependency, Faraday::ClientError => e
      ### Status codes
      ### * 204 2fa enabled for user in passport db
      ### * 500 server error (error from passport db)
      error_state =
        case e.try(:response).try(:[], :status)
        when 500
          [ERR_FROM_PASSPORT, e.try(:response).try(:[], :body)]
        else
          [ERR_UNKNOWN, e.message]
        end
      from_errors(error_state)
    else
      ### We should be good!
      from_attributes({user_id: user_id}.merge({disabled_at: Time.now}))
    end
  end
end
