import { Injectable } from '@angular/core';
import {
  HttpInterceptor,
  HttpEvent,
  HttpHandler,
  HttpRequest,
  HttpErrorResponse,
} from '@angular/common/http';
import {
  catchError,
  concatMap,
  Observable,
  retryWhen,
  of,
  throwError,
} from 'rxjs';
import { ToastrService } from 'ngx-toastr';
import { Router } from '@angular/router';
import { TranslatePipes } from '../pipes/translate/translate.pipe';
import { finalize } from 'rxjs/operators';
import { Location } from '@angular/common';

export enum ErrorCode {
  serverDown = 0,
  unauthorised = 401,
  apifailed = 520,
  client = 404,
}

@Injectable()

export class Httperror implements HttpInterceptor {
  constructor(private toastr: ToastrService, private router: Router, private state: Location, private translate : TranslatePipes) { }
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {

    return next.handle(req)
      .pipe(
        retryWhen((error) => this.retryRequest(error, 10)),
        catchError((error: HttpErrorResponse) => {
          const errorMessage: any = this.setError(error);
          return throwError((error) => {
            if (errorMessage?.['error']) {
              if (errorMessage?.['error']?.['message'])  {
                if(errorMessage['error']['message'] != '{"message": "Server Error"}{"message": "Server Error"}'){
                  this.toastr.error(this.translate.transform(errorMessage['error']['message']));
                }
              }
              else if(errorMessage['error'] == 'Internal Server Error'){
                
              }
              else{                
                if(errorMessage['error'] != '{"message": "Server Error"}{"message": "Server Error"}'){
                this.toastr.error(this.translate.transform(errorMessage['error']));
                }
              }
            }
            else if (typeof (errorMessage) === 'object') {
              for (const el in errorMessage) {
                
                if(Array.isArray(errorMessage[el])){
                  errorMessage[el].forEach(e => {
                    if(e != '{"message": "Server Error"}{"message": "Server Error"}'){
                    this.toastr.error(this.translate.transform(e));
                    }
                  }); 
                }
                
                if(errorMessage[el] != '{"message": "Server Error"}{"message": "Server Error"}'){
                  this.toastr.error(this.translate.transform(errorMessage[el]));
                }
              }
            }
            new Error(errorMessage);
          });
        })
      ).pipe(
        finalize(() => {
        }
        ),
      );
  }

  // Retry the request in case of error
  retryRequest(error: any, retryCount: number): any {

    return error.pipe(
      concatMap((checkErr: HttpErrorResponse, count: number) => {
        if (count <= retryCount) {
          switch (checkErr.status) {
            case ErrorCode.serverDown:
              return of(checkErr);
          }
        }
        return throwError(() => checkErr);
      })
    );
  }

  setError(error: HttpErrorResponse): string {
    let errorMessage:any = 'Unknow error occured';
    
    if (error?.error?.message == 'This action is unauthorized.') {
      this.router.navigate(['/restricted']);
    }
    if (error.status == 302 && error?.error?.message == 'ipblock') {
      this.router.navigate(['/restricted']);
    }
    if (error.status == 403) {
      this.router.navigate(['/restricted']);
    }
    if (error.status == 302 && error?.error?.message == 'captcha') {
      this.router.navigate(['/recaptcha'], { queryParams: { returnUrl: this.state.path() } });
    }
    if (error.status == 302 && error?.error?.message == 'licenseinfo') {
      this.router.navigate(['/admin/add-license-code']);
    }
    if (error.status == 503) {
      this.toastr.warning(this.translate.transform('Under Maintenance mode'));
    }
    else if (error.status == 429) {
      this.router.navigate(['/multiple-requests'], {
        queryParams: {
          returnUrl: this.state.path(),
        },
      });
    }
    else if (error.error instanceof ErrorEvent) {
      //Client side error
      errorMessage = error.error.message;
    } else if(error.error?.['errors']) {
      // Server side error
      if (error.status !== 0) {
        errorMessage = error.error?.['errors'];
      }
    }else{
      errorMessage = error;
    }
    return errorMessage;
  }
}
