import { TranslateService } from '@ngx-translate/core';
import { Logger } from 'src/app/service/logger.service';
import { ErrorHandler, Injectable } from '@angular/core';
import { ToastService } from 'src/app/service/toast.service';
import { HttpErrorResponse } from '@angular/common/http';
import { ApolloError } from '@apollo/client/errors';
import { MissingPermissionException } from 'src/app/model/utils/error';
import { GraphQLError } from 'graphql/error/GraphQLError';
import { ToastOptions } from 'src/app/model/utils/toast-options';

const logger = new Logger('ErrorHandler');

@Injectable({
  providedIn: 'root',
})
export class ErrorHandlingService implements ErrorHandler {
  constructor(
    private t: TranslateService,
    private toast: ToastService
  ) {}

  handleError(error: HttpErrorResponse | ApolloError) {
    if (error instanceof ApolloError) {
      if (error.graphQLErrors && error.graphQLErrors.length > 0) {
        this.handleGraphQlErrors(error.graphQLErrors as GraphQLError[]);
        return;
      }

      this.handleHttpError(error.networkError as HttpErrorResponse);
      return;
    }
    this.handleHttpError(error);
  }

  private handleHttpError(e: HttpErrorResponse) {
    let toast: {
      summary: string;
      detail?: string;
      error?: string;
      options?: ToastOptions;
    } = {
      summary: this.t.instant('common.error'),
      detail: e.message,
    };

    if (e.status === 401) {
      toast = {
        summary: this.t.instant('common.error'),
        detail: this.t.instant('error.unauthorized'),
      };
    }

    if (e.status === 403) {
      if (e.error && (e.error as MissingPermissionException).permissions) {
        const missingPermissions = (e.error as MissingPermissionException)
          .permissions;

        toast = {
          summary: this.t.instant('common.error'),
          detail: this.t.instant('error.missing_permissions', {
            permissions: missingPermissions.join(', '),
          }),
        };
      } else {
        toast = {
          summary: this.t.instant('common.error'),
          detail: this.t.instant('error.permission_denied'),
        };
      }
    }

    if (e.status === 500 && e.error && e.error.errors) {
      if (e.error.errors.length > 0) {
        toast = {
          summary: this.t.instant('common.api_error'),
          detail: e.error.errors[0].message,
        };
      }
    }

    this.toast.error(toast.summary, toast.detail, toast.error, toast.options);
    logger.error(e);
  }

  private handleGraphQlErrors(errors: GraphQLError[]) {
    errors.forEach((e: GraphQLError) => {
      this.toast.error(
        this.t.instant('common.api_error'),
        `${e.message}${e.path ? ' ' + e.path.join('.') : ''}`
      );
    });
  }
}
