import { Injector, runInInjectionContext } from '@angular/core';
import { AsyncValidatorFn } from '@angular/forms';
import { uniqueValueValidator } from '@aurora';
import { Apollo } from 'apollo-angular';
import { map } from 'rxjs';
import { checkUniqueUsernameAccountQuery } from '../../account/data-access/account.graphql';

/**
 * Async validator that consults `iamCheckUniqueUsernameAccount` to verify the
 * username is not already taken. In edit mode, pass `avoidValues: [item.username]`
 * so the user's own username is not flagged as duplicate (filter is server-side).
 *
 * The backend returns a boolean: `true` when the username is available.
 */
export const uniqueUsernameValidator = (
  injector: Injector,
  avoidValues: string[] = [],
): AsyncValidatorFn =>
  uniqueValueValidator<string>(
    (value, avoid) =>
      runInInjectionContext(injector, () =>
        injector.get(Apollo).query<{ iamCheckUniqueUsernameAccount: boolean }>({
          query: checkUniqueUsernameAccountQuery,
          variables: { username: value.toLowerCase(), avoidUsernames: avoid },
          fetchPolicy: 'no-cache',
        }),
      ).pipe(map((result) => result.data?.iamCheckUniqueUsernameAccount ?? false)),
    { avoidValues, errorKey: 'uniqueUsername' },
  );
