import { Injectable, Inject } from '@angular/core';
import { Router } from '@angular/router';

import { Actions, ofType, createEffect } from '@ngrx/effects';

import { of } from 'rxjs';
import {
  catchError,
  exhaustMap,
  map,
  tap,
  take,
  switchMap
} from 'rxjs/operators';

import {
  PiService,
  Login2Response,
  ResponseStatus
} from '@ucap-webmessenger/pi';
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
import {
  DialogService,
  ConfirmDialogComponent,
  ConfirmDialogData,
  ConfirmDialogResult
} from '@ucap-webmessenger/ui';

import {
  loginSuccess,
  loginFailure,
  loginRedirect,
  logout,
  logoutConfirmation,
  logoutConfirmationDismiss,
  webLogin,
  webLoginSuccess,
  webLoginFailure
} from './actions';
import { LoginInfo } from '../../../types';
import { AppAuthenticationService } from '../../../services/authentication.service';

@Injectable()
export class Effects {
  webLogin$ = createEffect(() =>
    this.actions$.pipe(
      ofType(webLogin),
      map(action => action),
      exhaustMap((params: { loginInfo: LoginInfo; rememberMe: boolean }) =>
        this.piService
          .login2({
            loginId: params.loginInfo.loginId,
            loginPw: params.loginInfo.loginPw,
            companyCode: params.loginInfo.companyCode
          })
          .pipe(
            map((res: Login2Response) => {
              if ('success' !== res.status.toLowerCase()) {
                return webLoginFailure({ error: 'Failed' });
              } else {
                return webLoginSuccess({
                  loginInfo: params.loginInfo,
                  rememberMe: params.rememberMe,
                  login2Response: res
                });
              }
            }),
            catchError(error => of(webLoginFailure({ error })))
          )
      )
    )
  );

  webLoginSuccess$ = createEffect(
    () =>
      this.actions$.pipe(
        ofType(webLoginSuccess),
        switchMap(params =>
          this.nativeService.checkForUpdates().pipe(
            map((update: boolean) => {
              if (!update) {
                this.appAuthenticationService.login(
                  params.loginInfo,
                  params.rememberMe
                );
                this.router.navigate(['/messenger']);
              }
            }),
            catchError(error => of(error))
          )
        )
      ),
    { dispatch: false }
  );

  loginRedirect$ = createEffect(
    () =>
      this.actions$.pipe(
        ofType(loginRedirect),
        tap(authed => {
          this.router.navigate(['/account/login']);
        })
      ),
    { dispatch: false }
  );

  logout$ = createEffect(() =>
    this.actions$.pipe(
      ofType(logout),
      map(action => action),
      map(() => {
        this.appAuthenticationService.logout();
        return loginRedirect();
      })
    )
  );

  logoutConfirmation$ = createEffect(() =>
    this.actions$.pipe(
      ofType(logoutConfirmation),
      exhaustMap(async () => {
        const result = await this.dialogService.open<
          ConfirmDialogComponent,
          ConfirmDialogData,
          ConfirmDialogResult
        >(ConfirmDialogComponent, {
          width: '220px',
          data: {
            title: 'Logout',
            message: 'Logout ?'
          }
        });

        return result.choice;
      }),
      map(result => (result ? logout() : logoutConfirmationDismiss()))
    )
  );

  constructor(
    private actions$: Actions,
    private router: Router,
    private piService: PiService,
    private appAuthenticationService: AppAuthenticationService,
    private dialogService: DialogService,
    @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService
  ) {}
}
