import request from 'superagent';
import { ProxyAgent } from 'proxy-agent';

export default class VaultService {

  constructor(config) {
      this.request = request;
      if (process.env.http_proxy){
        this.proxy = process.env.http_proxy;
        this.proxyAgent = new ProxyAgent();
      }
      this.token = false;
    if (config.vaultConfig.token) {
        this.token = config.vaultConfig.token;
      }
      this.config = config.vaultConfig;
  }

  async login() {
    let data = { "password": this.config.password };

      try {
        let response;
        if (this.proxy) {
          if (this.config.namespace){
            response = await this.request.post(this.config.endpoint + "/auth/userpass/login/" + this.config.user).set('X-Vault-Namespace', this.config.namespace).agent(this.proxyAgent).send(data);
          } else {
            response = await this.request.post(this.config.endpoint + "/auth/userpass/login/" + this.config.user).agent(this.proxyAgent).send(data);
          }
        } else {
          if (this.config.namespace){
            response = await this.request.post(this.config.endpoint + "/auth/userpass/login/" + this.config.user).set('X-Vault-Namespace', this.config.namespace).send(data);
          } else {
            response = await this.request.post(this.config.endpoint + "/auth/userpass/login/" + this.config.user).send(data);
          }
        }
        if (response.body.auth.entity_id) {
          this.token = response.body.auth.client_token;
        } else {
            throw new Error('Vault Service Login Response did not include token');
        }
      } catch (error) {
          throw new Error('Error vault service login: ' + error)
      }

  }

  async getSecret(path, key) {

      if (!path.startsWith('/') && !this.config.endpoint.endsWith('/')){
          path = '/' + path;
      }
      if (!path.endsWith('/')){
        path = path + '/' ;
      }
      path = path + key;

      try {
        if (!this.token) {
          await this.login();
        }
        let response;
        if (this.proxy) {
          if (this.config.namespace){
            response = await this.request.get(this.config.endpoint + path).agent(this.proxyAgent).set('X-Vault-Token', this.token).set('X-Vault-Namespace', this.config.namespace);
          } else {
            response = await this.request.get(this.config.endpoint + path).agent(this.proxyAgent).set('X-Vault-Token', this.token);
          }
        } else {
          if (this.config.namespace){
            response = await this.request.get(this.config.endpoint + path).set('X-Vault-Token', this.token).set('X-Vault-Namespace', this.config.namespace);
          } else {
            response = await this.request.get(this.config.endpoint + path).set('X-Vault-Token', this.token);
          }
        }
        if (response.body.data){
          let result = {};
          result[key] = response.body.data
          return result;
        } else {
          throw new Error('getSecret failed for:' + key);
        }
      } catch (error) {
        //retry
        try {
          if (!this.token) {
            await this.login();
          }
          let response;
          if (this.proxy) {
            if (this.config.namespace){
              response = await this.request.get(this.config.endpoint + path).agent(this.proxyAgent).set('X-Vault-Token', this.token).set('X-Vault-Namespace', this.config.namespace);
            } else {
              response = await this.request.get(this.config.endpoint + path).agent(this.proxyAgent).set('X-Vault-Token', this.token);
            }
          } else {
            if (this.config.namespace){
              response = await this.request.get(this.config.endpoint + path).set('X-Vault-Token', this.token).set('X-Vault-Namespace', this.config.namespace);
            } else {
              response = await this.request.get(this.config.endpoint + path).set('X-Vault-Token', this.token);
            }
          }
          if (response.body.data){
            let result = {};
            result[key] = response.body.data
            return result;
          } else {
            throw new Error('getSecret failed for:' + key);
          }
        } catch (error) {
            throw new Error('Error vault service getSecret on path: ' + this.config.endpoint + path + ' ERROR: ' + error)
        }
      }

  }
  async createUpdateSecret(path, key, data) {
      if (!path.startsWith('/') && !this.config.endpoint.endsWith('/')){
          path = '/' + path;
      }
      if (!path.endsWith('/')){
        path = path + '/' ;
      }
      path = path + key;

      try {
        if (!this.token) {
          await this.login();
        }
        let response;
        if (this.proxy) {
          if (this.config.namespace){
            response = await this.request.post(this.config.endpoint + path).send(data).agent(this.proxyAgent).set('X-Vault-Token', this.token).set('X-Vault-Namespace', this.config.namespace);
          } else {
            response = await this.request.post(this.config.endpoint + path).send(data).agent(this.proxyAgent).set('X-Vault-Token', this.token);
          }
        } else {
          if (this.config.namespace){
            response = await this.request.post(this.config.endpoint + path).send(data).set('X-Vault-Token', this.token).set('X-Vault-Namespace', this.config.namespace);
          } else {
            response = await this.request.post(this.config.endpoint + path).send(data).set('X-Vault-Token', this.token);
          }
        }
        if (response.body.data){
          let result = {};
          result[key] = response.body.data
          return result;
        } else {
          throw new Error('createUpdateSecret failed for:' + key);
        }
      } catch (error) {
        //retry
        try {
          if (!this.token) {
            await this.login();
          }
          let response;
          if (this.proxy) {
            if (this.config.namespace){
              response = await this.request.post(this.config.endpoint + path).send(data).agent(this.proxyAgent).set('X-Vault-Token', this.token).set('X-Vault-Namespace', this.config.namespace);
            } else {
              response = await this.request.post(this.config.endpoint + path).send(data).agent(this.proxyAgent).set('X-Vault-Token', this.token);
            }
          } else {
            if (this.config.namespace){
              response = await this.request.post(this.config.endpoint + path).send(data).set('X-Vault-Token', this.token).set('X-Vault-Namespace', this.config.namespace);
            } else {
              response = await this.request.post(this.config.endpoint + path).send(data).set('X-Vault-Token', this.token);
            }
          }
          if (response.body.data){
            let result = {};
            result[key] = response.body.data
            return result;
          } else {
            throw new Error('createUpdateSecret failed for:' + key);
          }
        } catch (error) {
          throw new Error('Error vault service createUpdateSecret: ' + error)
        }
      }

  }
}
