module Drops
  class User < Drops::Base
    self.primary_attribute = :twitch_user_id

    attributes :twitch_user_id, :service_user_id, :service_id, :login

    # find by canonical twitch user ID
    def self.find(service_id, twitch_user_id)
      self.reify({ twitch_user_id: twitch_user_id }, service_id)
    end

    def self.find_by_twitch_login(service_id, login)
      self.reify({ login: login }, service_id)
    end

    def self.find_by_service_user_id(service_id, service_user_id)
      response = get "/service/#{service_id}/serviceuser/#{service_user_id}"

      if response.success? and response.body["identifier"].present?
        self.reify({ twitch_user_id: response.body["identifier"] }, service_id, service_user_id)
      else
        from_errors("No user found for service #{service_id} / service user #{service_user_id}")
      end
    end

    protected

    def self.reify(user_by, service_id, service_user_id = nil)
      twitch_user = self.get_twitch_user(user_by)
      service_user_id = self.get_service_user_id(service_id, twitch_user.id) if service_user_id.nil?

      from_attributes({
        twitch_user_id: twitch_user.id,
        login: twitch_user.login,
        service_id: service_id,
        service_user_id: service_user_id,
      })
    rescue Exception => e
      from_errors(e.message)
    end

    def self.get_twitch_user(by)
      if by.has_key? :login
        user = Twitch::User.find_by_login(by[:login])

        raise "Could not find Twitch user with login #{by[:login]}" if user.nil?
      elsif by.has_key? :twitch_user_id
        begin
          user = Twitch::User.find(by[:twitch_user_id])
        rescue
          raise "Could not find Twitch user with id #{by[:twitch_user_id]}"
        end
      end

      user
    end

    def self.get_service_user_id(service_id, twitch_user_id)
      developer = Drops::Developer.find(service_id)
      response = get "/connection/#{developer.client_id}/#{twitch_user_id}"

      if response.success?
        response.body["identifier"]
      else
        raise "Unable to retrieve service user ID for service #{service_id} / user #{twitch_user_id}"
      end
    end
  end
end
