import { EventEmitter, Injectable } from '@angular/core';
import { HotToastService } from '@ngxpert/hot-toast';
import { catchError, delay, EMPTY, map, Observable, take, tap } from 'rxjs';
import {
  GetAnomaliesGQL,
  GetGroupedAnomaliesGQL,
  SetAnomalyToSleepGQL,
  AcceptAnomalyGQL,
  GetUpcomingToursGQL,
  PaginatedAnomaly,
  PaginatedAnomalyGroup,
} from '../../core/data-access/graphql/generated/generated';
import { faro, LogLevel } from '@grafana/faro-web-sdk';

@Injectable()
export class AnomaliesService {
  anomaliesRefresh$ = new EventEmitter<void>();
  upcomingToursQuery;
  upcomingTours$;

  constructor(
    private readonly getAnomaliesGql: GetAnomaliesGQL,
    private readonly getGroupedAnomaliesGql: GetGroupedAnomaliesGQL,
    private readonly setAnomalyToSleepGql: SetAnomalyToSleepGQL,
    private readonly acceptAnomalyGql: AcceptAnomalyGQL,
    private readonly upcomingToursGql: GetUpcomingToursGQL,
    private readonly toast: HotToastService
  ) {
    this.upcomingToursQuery = this.upcomingToursGql.watch(
      {},
      { pollInterval: 60 * 1000 }
    );

    this.upcomingTours$ = this.upcomingToursQuery.valueChanges;
  }

  getAnomaliesByPage(
    cursor: string,
    take: number = 10
  ): Observable<PaginatedAnomaly> {
    return this.getAnomaliesGql
      .fetch(
        { cursor, take },
        {
          fetchPolicy: 'no-cache',
        }
      )
      .pipe(
        map((queryResult) => queryResult.data.anomalies),
        catchError((err) => {
          console.error(err);
          return EMPTY;
        })
      );
  }

  getGroupedAnomaliesByPage(
    cursor: string,
    take: number = 10
  ): Observable<PaginatedAnomalyGroup> {
    return this.getGroupedAnomaliesGql
      .fetch(
        { cursor, take },
        {
          fetchPolicy: 'no-cache',
        }
      )
      .pipe(
        map(
          (queryResult) =>
            queryResult.data
              .groupedAnomalies as unknown as PaginatedAnomalyGroup
        ),
        catchError((err) => {
          console.error(err);
          return EMPTY;
        })
      );
  }

  setAnomalyToSleep(anomalyId: string): void {
    this.setAnomalyToSleepGql
      .mutate({ id: anomalyId })
      .pipe(
        take(1),
        tap(() => this.anomaliesRefresh$.emit()),
        tap((mutationResult) => {
          if (mutationResult.errors) {
            this.toast.error(
              'Leider ist etwas schief gelaufen, versuchen Sie es bitte nochmal'
            );
          } else {
            faro.api.pushLog([`Sleep anomaly ${anomalyId}`], {
              context: {
                payload: anomalyId,
              },
              level: LogLevel.TRACE,
            })
            this.toast.success(
              'Die Anomalie wurde für eine Stunde stummgeschaltet!'
            );
          }
        })
      )
      .subscribe();
  }

  acceptAnomaly(anomalyId: string): void {

    this.acceptAnomalyGql
      .mutate({ id: anomalyId })
      .pipe(
        take(1),
        delay(10),
        tap(() => this.anomaliesRefresh$.emit()),
        tap((mutationResult) => {
          if (mutationResult.errors) {
            this.toast.error(
              'Leider ist etwas schief gelaufen, versuchen Sie es bitte nochmal'
            );
          } else {
            faro.api.pushLog([`Accept anomaly ${anomalyId}`], {
              context: {
                payload: anomalyId,
              },
              level: LogLevel.TRACE,
            })
            this.toast.success('Die Anomalie wurde akzeptiert!');
          }
        })
      )
      .subscribe();
  }
}
