import { Injectable, Provider } from '@angular/core';
import { Observable } from 'rxjs';
import { Apollo, gql } from 'apollo-angular';
import { catchError, map } from 'rxjs/operators';
import { SpinnerService } from 'src/app/service/spinner.service';
import { FeatureFlag } from 'src/app/model/entities/feature-flag';

@Injectable()
export class FeatureFlagsDataService {
  constructor(
    private spinner: SpinnerService,
    private apollo: Apollo
  ) {}

  load(): Observable<FeatureFlag[]> {
    return this.apollo
      .query<{ featureFlags: FeatureFlag[] }>({
        query: gql`
          query GetFeatureFlags {
            featureFlags {
              key
              value
            }
          }
        `,
        variables: {},
      })
      .pipe(
        catchError(err => {
          this.spinner.hide();
          throw err;
        })
      )
      .pipe(map(result => result.data.featureFlags));
  }

  loadByKey(key: string): Observable<FeatureFlag> {
    return this.apollo
      .query<{ featureFlags: FeatureFlag[] }>({
        query: gql`
          query getFeatureFlag($key: String!) {
            featureFlag(key: $key) {
              key
              value
            }
          }
        `,
        variables: {
          key,
        },
      })
      .pipe(
        catchError(err => {
          this.spinner.hide();
          throw err;
        })
      )
      .pipe(map(result => result.data.featureFlags[0]));
  }

  onUpdate(): Observable<void> {
    return this.apollo
      .subscribe<{ featureFlagChange: void }>({
        query: gql`
          subscription onFeatureFlagChange {
            featureFlagChange
          }
        `,
      })
      .pipe(map(result => result.data?.featureFlagChange));
  }

  change(object: FeatureFlag): Observable<FeatureFlag | undefined> {
    return this.apollo
      .mutate<{ featureFlag: { change: FeatureFlag } }>({
        mutation: gql`
          mutation changeFeatureFlag($input: FeatureFlagInput!) {
            featureFlag {
              change(input: $input) {
                key
                value
              }
            }
          }
        `,
        variables: {
          input: {
            key: object.key,
            value: object.value,
          },
        },
      })
      .pipe(
        catchError(err => {
          this.spinner.hide();
          throw err;
        })
      )
      .pipe(map(result => result.data?.featureFlag.change));
  }

  static provide(): Provider[] {
    return [FeatureFlagsDataService];
  }
}
