import _ from 'lodash';
import qs from 'qs';
import moment from 'moment'
import { checkStatus, parseJSON, getStandardHeaders } from './clientUtils.js';

class Client {
  constructor() {
    this.tenantId = process.env.REACT_APP_TENANT_ID
    this.clientId = process.env.REACT_APP_CLIENT_ID
    this.adminGroupId = process.env.REACT_APP_ADMIN_GROUP_ID
    this.domainHint = process.env.REACT_APP_DOMAIN_HINT
    this.redirectUrl = window.location.origin + '/callback/azure'

    const token = JSON.parse(sessionStorage.getItem('azureToken'));
    if (token !== null) {
      this.processToken(token)
      this.isAdmin = JSON.parse(sessionStorage.getItem('isAdmin'));
    }
    else {
      this.accessToken = null
      this.idToken = null
      this.isAuthenticated = false
      this.isAdmin = null
      this.defaultHeaders = getStandardHeaders()
    }
  }

  authenticate(from) {
    const state = from || '/'

    const params = {
      client_id: this.clientId,
      response_type: 'id_token token',
      redirect_uri: this.redirectUrl,
      state: state.pathname || state,
      scope: "openid https://graph.microsoft.com/user.read",
      response_mode: 'fragment',
      nonce: '678910',
      domain_hint: this.domainHint,
      resource: 'https://graph.microsoft.com'
    }

    window.location.href = `https://login.microsoftonline.com/${this.tenantId}/oauth2/authorize?${qs.stringify(params)}`
  }

  grantAdminPermissions(from) {
    const state = from || { pathname: '/' }

    const params = {
      client_id: this.clientId,
      redirect_uri: window.location.origin + '/admin-consent',
      state: state.pathname || state,
      // scope: "openid https://graph.microsoft.com/user.read",
    }
    window.location.href = `https://login.microsoftonline.com/${this.tenantId}/adminconsent?${qs.stringify(params)}`
  }


  getToken(hash, cb) {
    // response contains: access_token,expires_in,id_token,scope,session_state,state,token_type
    const tokenInfo = this.extractTokenFromHash(hash)
    if (tokenInfo.error)
      return

    const tokenValidUntil = new moment().add(tokenInfo.expires_in, 'seconds')
    tokenInfo.tokenValidUntil = tokenValidUntil.toISOString();
    sessionStorage.setItem('azureToken', JSON.stringify(tokenInfo))

    this.processToken(tokenInfo);
    this.checkIfUserIsAdmin()
      .then(isAdmin => {
        this.isAdmin = isAdmin
        sessionStorage.setItem('isAdmin', JSON.stringify(this.isAdmin))
        cb(this.isAuthenticated, this.isAdmin, decodeURIComponent(tokenInfo.state))
      })
      .catch(err => {
        this.isAdmin = null
        sessionStorage.setItem('isAdmin', JSON.stringify(this.isAdmin))
        cb(this.isAuthenticated, this.isAdmin, decodeURIComponent(tokenInfo.state))
      })
  }



  getTokenOld(hash, cb) {
    // response contains: access_token,expires_in,id_token,scope,session_state,state,token_type
    const tokenInfo = this.extractTokenFromHash(hash)
    if (tokenInfo.error)
      return

    const tokenValidUntil = new moment().add(tokenInfo.expires_in, 'seconds')
    tokenInfo.tokenValidUntil = tokenValidUntil.toISOString();
    sessionStorage.setItem('azureToken', JSON.stringify(tokenInfo))

    this.processToken(tokenInfo);
    this.checkIfUserIsAdmin()
      .then(isAdmin => {
        this.isAdmin = isAdmin
        sessionStorage.setItem('isAdmin', JSON.stringify(this.isAdmin))
        cb(this.isAuthenticated, this.isAdmin, decodeURIComponent(tokenInfo.state))
      })
      .catch(err => {
        this.isAdmin = null
        sessionStorage.setItem('isAdmin', JSON.stringify(this.isAdmin))
        cb(this.isAuthenticated, this.isAdmin, decodeURIComponent(tokenInfo.state))
      })
  }

  processToken(tokenInfo) {
    this.accessToken = tokenInfo.access_token
    this.idToken = tokenInfo.id_token
    this.isAuthenticated = true
    this.defaultHeaders = getStandardHeaders(this.accessToken)
    this.tokenValidUntil = moment(tokenInfo.tokenValidUntil)
  }

  extractTokenFromHash(hash) {
    return _.chain(hash.substring(1).split('&'))
      // eslint-disable-next-line
      .map(function (item) { if (item) return item.split('='); })
      .compact()
      .fromPairs()
      .value();
  }

  SignOut() {
    sessionStorage.removeItem('azureToken')
    sessionStorage.removeItem('isAdmin')
    this.accessToken = null
    this.idToken = null
    this.isAuthenticated = false
    this.isAdmin = null
    this.defaultHeaders = getStandardHeaders()
  }

  getUser() {
    return fetch('https://graph.microsoft.com/v1.0/me', {
      method: 'get',
      headers: this.defaultHeaders,
    }).then(checkStatus)
      .then(parseJSON)
      .then(json => new Promise((resolve, reject) => {
        const user = {
          name: json.displayName,
          email: json.mail,
          id: json.id,
          upn: json.userPrincipalName
        }
        resolve(user)
      })
      )
  }

  checkIfUserIsAdmin() {
    return fetch('https://graph.microsoft.com/v1.0/me/memberOf', {
      method: 'get',
      headers: this.defaultHeaders,
    }).then(checkStatus)
      .then(parseJSON)
      .then(json => new Promise((resolve, reject) => {
        if (json && json.value)
          resolve(_.filter(json.value, { id: this.adminGroupId }).length === 1)
        else
          reject('problem', json);
      })
      )
  }
  // getDirectoryName() {
  //   return fetch('https://graph.microsoft.com/v1.0/organization', {
  //     method: 'get',
  //     headers: this.defaultHeaders,
  //   }).then(checkStatus)
  //     .then(parseJSON)
  // }
}

export default new Client();

@@ -304,19 +304,42 @@
 nGroupId
+s
  = 
+this.getAdminGroupIds(
 process.
@@ -366,16 +366,17 @@
 GROUP_ID
+)
 %0A    thi
@@ -4485,16 +4485,158 @@
 ()%0A  %7D%0A%0A
+  getAdminGroupIds(groupIdsString) %7B%0A    if (typeof groupIdsString !== 'string')%0A      return null%0A%0A    return groupIdsString.split(';')%0A  %7D%0A%0A
   getUse
@@ -5365,68 +5365,45 @@
 lve(
-_.filter(json.value, %7B id: this.adminGroupId %7D).length === 1
+this.isUserInAnAdminGroup(json.value)
 )%0A  
@@ -5469,16 +5469,196 @@
   )%0A  %7D%0A
+  %0A  isUserInAnAdminGroup(groups) %7B%0A    console.log(this.adminGroupIds)%0A%0A    return _(groups)%0A      .keyBy('id')%0A      .at(this.adminGroupIds)%0A      .value()%0A      .length %3E 0%0A  %7D%0A
   // get

Add ability to specify more than one admin group