module Secrets
  class SandstormLoader
    include Code::Justin::Tv::Sse::Sandstorm

    def self.load!
      return unless Settings.sandstorm_addr
      Settings[:secrets] = Settings.secrets.deep_merge load_from_sandstorm
    end

    def self.load_from_sandstorm
      {
        'chaos' => {
          'sentry' => {
            'client_id' => secret_value(key: 'chaos.sentry.client_id'),
            'client_secret' => secret_value(key: 'chaos.sentry.client_secret'),
          }
        },
        'duo' => {
          'skey' => secret_value(key: 'duo.skey'),
        },
        'openid' => {
          'client_id' => secret_value(key: 'openid.client_id'),
          'client_secret' => secret_value(key: 'openid.client_secret'),
        },
        'passport' => {
          'jwt_secret' => secret_value(key: 'password_jwt_secret'),
        },
        'rollbar_token' => secret_value(key: 'rollbar_token'),
        'secret_token' => secret_value(key: 'secret_token')
      }
    end

    def self.client
      @client ||= SandstormClient.new(connection)
      @client
    end

    def self.connection
      if Settings.sandstorm_addr.start_with?('http')
        Faraday::Connection.new(
          Settings.sandstorm_addr + '/twirp/',
          request: { open_timeout: 60, timeout: 60 }
        )
      else
        return Faraday.new('unix:///twirp/') do |f|
          f.adapter :excon, {
            socket: Settings.sandstorm_addr,
            timeout: 60,
          }
        end
      end
    end

    def self.secret_value(options = {})
      res = client.get_decrypted_secret(
        GetDecryptedSecretReq.new(name: secret_key(options))
      )
      raise res.error.to_s if res.error
      return res.data.plaintext
    end

    def self.secret_key(options = {})
      group = options[:group] || 'web-rails'
      project = options[:project] || 'admin-panel'
      environment = options[:environment] || Settings.sandstorm_env
      key = options[:key]
      return [group, project, environment, key].join('/')
    end
  end
end
