// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';

// TODO(dit): Split `id` and `oauth2` "services" for mocking. https://github.com/flutter/flutter/issues/120657
import 'package:google_identity_services_web/id.dart';
import 'package:google_identity_services_web/oauth2.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
// ignore: unnecessary_import
import 'package:js/js.dart';
import 'package:js/js_util.dart';

import 'people.dart' as people;
import 'utils.dart' as utils;

/// A client to hide (most) of the interaction with the GIS SDK from the plugin.
///
/// (Overridable for testing)
class GisSdkClient {
  /// Create a GisSdkClient object.
  GisSdkClient({
    required List<String> initialScopes,
    required String clientId,
    bool loggingEnabled = false,
    String? hostedDomain,
  }) : _initialScopes = initialScopes {
    if (loggingEnabled) {
      id.setLogLevel('debug');
    }
    // Configure the Stream objects that are going to be used by the clients.
    _configureStreams();

    // Initialize the SDK clients we need.
    _initializeIdClient(
      clientId,
      onResponse: _onCredentialResponse,
    );

    _tokenClient = _initializeTokenClient(
      clientId,
      hostedDomain: hostedDomain,
      onResponse: _onTokenResponse,
      onError: _onTokenError,
    );
  }

  // Configure the credential (authentication) and token (authorization) response streams.
  void _configureStreams() {
    _tokenResponses = StreamController<TokenResponse>.broadcast();
    _credentialResponses = StreamController<CredentialResponse>.broadcast();
    _tokenResponses.stream.listen((TokenResponse response) {
      _lastTokenResponse = response;
    }, onError: (Object error) {
      _lastTokenResponse = null;
    });
    _credentialResponses.stream.listen((CredentialResponse response) {
      _lastCredentialResponse = response;
    }, onError: (Object error) {
      _lastCredentialResponse = null;
    });
  }

  // Initializes the `id` SDK for the silent-sign in (authentication) client.
  void _initializeIdClient(
    String clientId, {
    required CallbackFn onResponse,
  }) {
    // Initialize `id` for the silent-sign in code.
    final IdConfiguration idConfig = IdConfiguration(
      client_id: clientId,
      callback: allowInterop(onResponse),
      cancel_on_tap_outside: false,
      auto_select: true, // Attempt to sign-in silently.
    );
    id.initialize(idConfig);
  }

  // Handle a "normal" credential (authentication) response.
  //
  // (Normal doesn't mean successful, this might contain `error` information.)
  void _onCredentialResponse(CredentialResponse response) {
    if (response.error != null) {
      _credentialResponses.addError(response.error!);
    } else {
      _credentialResponses.add(response);
    }
  }

  // Creates a `oauth2.TokenClient` used for authorization (scope) requests.
  TokenClient _initializeTokenClient(
    String clientId, {
    String? hostedDomain,
    required TokenClientCallbackFn onResponse,
    required ErrorCallbackFn onError,
  }) {
    // Create a Token Client for authorization calls.
    final TokenClientConfig tokenConfig = TokenClientConfig(
      client_id: clientId,
      hosted_domain: hostedDomain,
      callback: allowInterop(_onTokenResponse),
      error_callback: allowInterop(_onTokenError),
      // `scope` will be modified by the `signIn` method, in case we need to
      // backfill user Profile info.
      scope: ' ',
    );
    return oauth2.initTokenClient(tokenConfig);
  }

  // Handle a "normal" token (authorization) response.
  //
  // (Normal doesn't mean successful, this might contain `error` information.)
  void _onTokenResponse(TokenResponse response) {
    if (response.error != null) {
      _tokenResponses.addError(response.error!);
    } else {
      _tokenResponses.add(response);
    }
  }

  // Handle a "not-directly-related-to-authorization" error.
  //
  // Token clients have an additional `error_callback` for miscellaneous
  // errors, like "popup couldn't open" or "popup closed by user".
  void _onTokenError(Object? error) {
    // This is handled in a funky (js_interop) way because of:
    // https://github.com/dart-lang/sdk/issues/50899
    _tokenResponses.addError(getProperty(error!, 'type'));
  }

  /// Attempts to sign-in the user using the OneTap UX flow.
  ///
  /// If the user consents, to OneTap, the [GoogleSignInUserData] will be
  /// generated from a proper [CredentialResponse], which contains `idToken`.
  /// Else, it'll be synthesized by a request to the People API later, and the
  /// `idToken` will be null.
  Future<GoogleSignInUserData?> signInSilently() async {
    final Completer<GoogleSignInUserData?> userDataCompleter =
        Completer<GoogleSignInUserData?>();

    // Ask the SDK to render the OneClick sign-in.
    //
    // And also handle its "moments".
    id.prompt(allowInterop((PromptMomentNotification moment) {
      _onPromptMoment(moment, userDataCompleter);
    }));

    return userDataCompleter.future;
  }

  // Handles "prompt moments" of the OneClick card UI.
  //
  // See: https://developers.google.com/identity/gsi/web/guides/receive-notifications-prompt-ui-status
  Future<void> _onPromptMoment(
    PromptMomentNotification moment,
    Completer<GoogleSignInUserData?> completer,
  ) async {
    if (completer.isCompleted) {
      return; // Skip once the moment has been handled.
    }

    if (moment.isDismissedMoment() &&
        moment.getDismissedReason() ==
            MomentDismissedReason.credential_returned) {
      // Kick this part of the handler to the bottom of the JS event queue, so
      // the _credentialResponses stream has time to propagate its last value,
      // and we can use _lastCredentialResponse.
      return Future<void>.delayed(Duration.zero, () {
        completer
            .complete(utils.gisResponsesToUserData(_lastCredentialResponse));
      });
    }

    // In any other 'failed' moments, return null and add an error to the stream.
    if (moment.isNotDisplayed() ||
        moment.isSkippedMoment() ||
        moment.isDismissedMoment()) {
      final String reason = moment.getNotDisplayedReason()?.toString() ??
          moment.getSkippedReason()?.toString() ??
          moment.getDismissedReason()?.toString() ??
          'unknown_error';

      _credentialResponses.addError(reason);
      completer.complete(null);
    }
  }

  /// Starts an oauth2 "implicit" flow to authorize requests.
  ///
  /// The new GIS SDK does not return user authentication from this flow, so:
  ///   * If [_lastCredentialResponse] is **not** null (the user has successfully
  ///     `signInSilently`), we return that after this method completes.
  ///   * If [_lastCredentialResponse] is null, we add [people.scopes] to the
  ///     [_initialScopes], so we can retrieve User Profile information back
  ///     from the People API (without idToken). See [people.requestUserData].
  Future<GoogleSignInUserData?> signIn() async {
    // If we already know the user, use their `email` as a `hint`, so they don't
    // have to pick their user again in the Authorization popup.
    final GoogleSignInUserData? knownUser =
        utils.gisResponsesToUserData(_lastCredentialResponse);
    // This toggles a popup, so `signIn` *must* be called with
    // user activation.
    _tokenClient.requestAccessToken(OverridableTokenClientConfig(
      prompt: knownUser == null ? 'select_account' : '',
      hint: knownUser?.email,
      scope: <String>[
        ..._initialScopes,
        // If the user hasn't gone through the auth process,
        // the plugin will attempt to `requestUserData` after,
        // so we need extra scopes to retrieve that info.
        if (_lastCredentialResponse == null) ...people.scopes,
      ].join(' '),
    ));

    await _tokenResponses.stream.first;

    return _computeUserDataForLastToken();
  }

  // This function returns the currently signed-in [GoogleSignInUserData].
  //
  // It'll do a request to the People API (if needed).
  Future<GoogleSignInUserData?> _computeUserDataForLastToken() async {
    // If the user hasn't authenticated, request their basic profile info
    // from the People API.
    //
    // This synthetic response will *not* contain an `idToken` field.
    if (_lastCredentialResponse == null && _requestedUserData == null) {
      assert(_lastTokenResponse != null);
      _requestedUserData = await people.requestUserData(_lastTokenResponse!);
    }
    // Complete user data either with the _lastCredentialResponse seen,
    // or the synthetic _requestedUserData from above.
    return utils.gisResponsesToUserData(_lastCredentialResponse) ??
        _requestedUserData;
  }

  /// Returns a [GoogleSignInTokenData] from the latest seen responses.
  GoogleSignInTokenData getTokens() {
    return utils.gisResponsesToTokenData(
      _lastCredentialResponse,
      _lastTokenResponse,
    );
  }

  /// Revokes the current authentication.
  Future<void> signOut() async {
    clearAuthCache();
    id.disableAutoSelect();
  }

  /// Revokes the current authorization and authentication.
  Future<void> disconnect() async {
    if (_lastTokenResponse != null) {
      oauth2.revoke(_lastTokenResponse!.access_token);
    }
    signOut();
  }

  /// Returns true if the client has recognized this user before.
  Future<bool> isSignedIn() async {
    return _lastCredentialResponse != null || _requestedUserData != null;
  }

  /// Clears all the cached results from authentication and authorization.
  Future<void> clearAuthCache() async {
    _lastCredentialResponse = null;
    _lastTokenResponse = null;
    _requestedUserData = null;
  }

  /// Requests the list of [scopes] passed in to the client.
  ///
  /// Keeps the previously granted scopes.
  Future<bool> requestScopes(List<String> scopes) async {
    _tokenClient.requestAccessToken(OverridableTokenClientConfig(
      scope: scopes.join(' '),
      include_granted_scopes: true,
    ));

    await _tokenResponses.stream.first;

    return oauth2.hasGrantedAllScopes(_lastTokenResponse!, scopes);
  }

  // The scopes initially requested by the developer.
  //
  // We store this because we might need to add more at `signIn`. If the user
  // doesn't `silentSignIn`, we expand this list to consult the People API to
  // return some basic Authentication information.
  final List<String> _initialScopes;

  // The Google Identity Services client for oauth requests.
  late TokenClient _tokenClient;

  // Streams of credential and token responses.
  late StreamController<CredentialResponse> _credentialResponses;
  late StreamController<TokenResponse> _tokenResponses;

  // The last-seen credential and token responses
  CredentialResponse? _lastCredentialResponse;
  TokenResponse? _lastTokenResponse;

  // If the user *authenticates* (signs in) through oauth2, the SDK doesn't return
  // identity information anymore, so we synthesize it by calling the PeopleAPI
  // (if needed)
  //
  // (This is a synthetic _lastCredentialResponse)
  GoogleSignInUserData? _requestedUserData;
}
