module TwitterClient
  # Twitter client (users twitter gem as a backend)
  class Client
    class << self
      # adapted from https://api.rubyonrails.org/classes/Module.html#method-i-delegate_missing_to
      def method_missing(method, *args, &block)
        return super unless target.respond_to?(method, false)

        request do
          target.public_send(method, *args, &block)
        end
      end

      # adapted from https://api.rubyonrails.org/classes/Module.html#method-i-delegate_missing_to
      def respond_to_missing?(method, _include_all = false)
        target.respond_to?(method, false) || super
      end

      private

      def request
        Honeycomb.add_field("name", "twitter.client")
        yield
      rescue Twitter::Error => e
        record_error(e)
        handle_error(e)
      end

      def record_error(exception)
        class_name = exception.class.name.demodulize

        Honeycomb.add_field("twitter.result", "error")
        Honeycomb.add_field("twitter.error", class_name)
        ForemStatsClient.increment(
          "twitter.errors",
          tags: ["error:#{class_name}", "message:#{exception.message}"],
        )
      end

      def handle_error(exception)
        class_name = exception.class.name.demodulize

        # raise specific error if known, generic one if unknown
        error_class = "::TwitterClient::Errors::#{class_name}".safe_constantize
        raise error_class, exception.message if error_class

        error_class = case exception
                      when Twitter::Error::ClientError
                        TwitterClient::Errors::ClientError
                      when Twitter::Error::ServerError
                        TwitterClient::Errors::ServerError
                      else
                        TwitterClient::Errors::Error
                      end

        raise error_class, exception.message
      end

      def target
        Twitter::REST::Client.new(
          consumer_key: Settings::Authentication.twitter_key.presence || ApplicationConfig["TWITTER_KEY"],
          consumer_secret: Settings::Authentication.twitter_secret.presence || ApplicationConfig["TWITTER_SECRET"],
          user_agent: "TwitterRubyGem/#{Twitter::Version} (#{URL.url})",
          timeouts: {
            connect: 5,
            read: 5,
            write: 5
          },
        )
      end
    end
  end
end
