import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';

import { Injectable } from '@angular/core';
import {
  CanActivate,
  ActivatedRouteSnapshot,
  RouterStateSnapshot,
  UrlTree,
  Router
} from '@angular/router';

import { Store } from '@ngrx/store';

import { LogService } from '@ucap/ng-logger';
import { PiService } from '@ucap/ng-pi';

import { LoginActions } from '@ucap/ng-store-authentication';

import { AppAuthenticationService } from '@app/services/app-authentication.service';

@Injectable({
  providedIn: 'root'
})
export class AppAuthenticationGuard implements CanActivate {
  constructor(
    private piService: PiService,
    private appAuthenticationService: AppAuthenticationService,
    private store: Store<any>,
    private router: Router,
    private logService: LogService
  ) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ):
    | boolean
    | UrlTree
    | Observable<boolean | UrlTree>
    | Promise<boolean | UrlTree> {
    return new Promise<boolean | UrlTree>((resolve, reject) => {
      const loggedIn = this.appAuthenticationService.loggedIn();
      if (loggedIn) {
        resolve(true);
        return;
      }

      const userStore = this.appAuthenticationService.useAutoLogin();
      if (!userStore) {
        this.router.navigateByUrl('/account/login');
        resolve(false);
        return;
      }

      const loginSession = this.appAuthenticationService.getLoginSession();

      const onWebLoginFailure = (error: any) => {
        userStore.settings.general.autoLogin = false;
        this.appAuthenticationService.setUserStore(userStore);

        this.router.navigateByUrl('/account/login');
        resolve(false);
      };

      this.piService
        .login2({
          companyCode: userStore.companyCode,
          loginId: userStore.loginId,
          loginPw: userStore.loginPw,
          deviceType: loginSession.deviceType
        })
        .pipe(take(1))
        .subscribe(
          (res) => {
            if ('success' !== res.status.toLowerCase()) {
              onWebLoginFailure(res.status);
              return;
            } else {
              this.store.dispatch(
                LoginActions.webLoginSuccess({
                  companyCode: userStore.companyCode,
                  loginId: userStore.loginId,
                  loginPw: userStore.loginPw,
                  autoLogin: true,
                  rememberMe: userStore.rememberMe,
                  login2Response: res
                })
              );
              resolve(true);
              return;
            }
          },
          (error) => {
            onWebLoginFailure(error);
          }
        );
    });
  }
}
