import { Injectable } from '@angular/core';
import { throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { Setting } from 'src/app/model/entities/setting';
import { Apollo, gql } from 'apollo-angular';
import { Logger } from 'src/app/service/logger.service';
import { AuthService } from 'src/app/service/auth.service';

const log = new Logger('UserSettings');

@Injectable({
  providedIn: 'root',
})
export class UserSettingsService {
  constructor(
    private apollo: Apollo,
    private auth: AuthService
  ) {}

  get(key: string): Promise<string | undefined> {
    if (!this.auth.isLoggedIn()) {
      log.debug('get', key, 'not logged in');
      return Promise.resolve(undefined);
    }

    log.debug('get', key);
    return new Promise((resolve, reject) => {
      this.apollo
        .query<{ userSettings: Setting[] }>({
          query: gql`
            query getUserSetting($key: String!) {
              userSettings(key: $key) {
                key
                value
              }
            }
          `,
          variables: {
            key,
          },
        })
        .pipe(
          catchError(err => {
            throw err;
          })
        )
        .pipe(
          map(result =>
            result.data.userSettings?.length > 0
              ? result.data.userSettings[0]
              : undefined
          )
        )
        .pipe(
          catchError(err => {
            reject(err);
            return throwError(() => err);
          })
        )
        .subscribe(setting => {
          log.debug('Got', key, setting);
          resolve(setting?.value);
        });
    });
  }

  set(key: string, value: string): Promise<void> {
    if (!this.auth.isLoggedIn()) {
      log.debug('set', key, value, 'not logged in');
      return Promise.resolve(undefined);
    }

    log.debug('set', key, value);
    return new Promise((resolve, reject) => {
      this.apollo
        .mutate<{ userSetting: { change: Setting } }>({
          mutation: gql`
            mutation changeUserSetting($input: UserSettingInput!) {
              userSetting {
                change(input: $input) {
                  key
                  value
                }
              }
            }
          `,
          variables: {
            input: {
              key: key,
              value: value,
            },
          },
        })
        .pipe(
          catchError(err => {
            throw err;
          })
        )
        .pipe(map(result => result.data?.userSetting.change))
        .pipe(
          catchError(err => {
            reject(err);
            return throwError(() => err);
          })
        )
        .subscribe(() => {
          resolve();
        });
    });
  }
}
