import { Injectable } from '@angular/core';
import { OAuthService, JwksValidationHandler } from 'angular-oauth2-oidc';
import { SsoInterface } from './sso.interface';
import { isNullOrUndefined } from 'util';
import { NativeContainerService } from 'native-container';

@Injectable({
  providedIn: 'root',
})
export class SsoService {
  constructor(private oauthService: OAuthService, private externalService: SsoInterface, private native: NativeContainerService) {}

  public registerAuthentication() {
    this.oauthService.configure(this.externalService.getConfigurations());
    this.oauthService.tokenValidationHandler = new JwksValidationHandler();

    if (!!this.oauthService.silentRefreshRedirectUri) {
      this.oauthService.setupAutomaticSilentRefresh();
    }

    return this.oauthService.loadDiscoveryDocumentAndTryLogin().then((_) => {
      const hasIdToken = !!this.getIdToken();
      const hasAccessToken = !!this.getToken();
      const isLoggedIn = hasIdToken && hasAccessToken;

      if (!isLoggedIn) {
        this.login();
      }

      return new Promise((resolve) => resolve());
    });
  }

  public isAuthenticated(): boolean {
    return !!this.oauthService.getIdentityClaims();
  }

  public getIdToken(): string {
    return this.oauthService.getIdToken();
  }

  public getToken(): string {
    return this.oauthService.getAccessToken();
  }

  public getClaims(): object {
    return this.oauthService.getIdentityClaims();
  }

  public keyCardLogin(token: string) {
    this.oauthService.configure(this.externalService.getConfigurations());
    this.oauthService.tokenValidationHandler = new JwksValidationHandler();
    this.oauthService.customQueryParams = {
      temp_token: token,
    };
    this.login();
  }

  public login() {
    this.oauthService.initLoginFlow();
  }

  public logoff() {
    this.oauthService.logOut();
    if (this.native.isUiWebview().isNative) {
      this.native.openScanner('scanLogin');
    }
  }

  public getTokenClaims() {
    const token = this.oauthService.getAccessToken();
    return this.parseJwt(token);
  }

  public getClaimByKey(key: string) {
    const claims = this.getTokenClaims();
    if (isNullOrUndefined(claims)) {
      return null;
    }
    return claims[key];
  }

  public parseJwt(token: string) {
    if (isNullOrUndefined(token)) {
      return null;
    }
    const base64Url = token.split('.')[1];
    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    return JSON.parse(window.atob(base64));
  }
}
