// 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';
import 'dart:html' as html;

import 'package:flutter/foundation.dart' show visibleForTesting;
import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
import 'package:js/js.dart';

import 'src/js_interop/gapiauth2.dart' as auth2;
import 'src/load_gapi.dart' as gapi;
import 'src/utils.dart' show gapiUserToPluginUserData;

const String _kClientIdMetaSelector = 'meta[name=google-signin-client_id]';
const String _kClientIdAttributeName = 'content';

/// This is only exposed for testing. It shouldn't be accessed by users of the
/// plugin as it could break at any point.
@visibleForTesting
String gapiUrl = 'https://apis.google.com/js/platform.js';

/// Implementation of the google_sign_in plugin for Web.
class GoogleSignInPlugin extends GoogleSignInPlatform {
  /// Constructs the plugin immediately and begins initializing it in the
  /// background.
  ///
  /// The plugin is completely initialized when [initialized] completed.
  GoogleSignInPlugin() {
    _autoDetectedClientId = html
        .querySelector(_kClientIdMetaSelector)
        ?.getAttribute(_kClientIdAttributeName);

    _isGapiInitialized = gapi.inject(gapiUrl).then((_) => gapi.init());
  }

  late Future<void> _isGapiInitialized;
  late Future<void> _isAuthInitialized;
  bool _isInitCalled = false;

  // This method throws if init or initWithParams hasn't been called at some
  // point in the past. It is used by the [initialized] getter to ensure that
  // users can't await on a Future that will never resolve.
  void _assertIsInitCalled() {
    if (!_isInitCalled) {
      throw StateError(
        'GoogleSignInPlugin::init() or GoogleSignInPlugin::initWithParams() '
        'must be called before any other method in this plugin.',
      );
    }
  }

  /// A future that resolves when both GAPI and Auth2 have been correctly initialized.
  @visibleForTesting
  Future<void> get initialized {
    _assertIsInitCalled();
    return Future.wait(<Future<void>>[_isGapiInitialized, _isAuthInitialized]);
  }

  String? _autoDetectedClientId;

  /// Factory method that initializes the plugin with [GoogleSignInPlatform].
  static void registerWith(Registrar registrar) {
    GoogleSignInPlatform.instance = GoogleSignInPlugin();
  }

  @override
  Future<void> init({
    List<String> scopes = const <String>[],
    SignInOption signInOption = SignInOption.standard,
    String? hostedDomain,
    String? clientId,
  }) {
    return initWithParams(SignInInitParameters(
      scopes: scopes,
      signInOption: signInOption,
      hostedDomain: hostedDomain,
      clientId: clientId,
    ));
  }

  @override
  Future<void> initWithParams(SignInInitParameters params) async {
    final String? appClientId = params.clientId ?? _autoDetectedClientId;
    assert(
        appClientId != null,
        'ClientID not set. Either set it on a '
        '<meta name="google-signin-client_id" content="CLIENT_ID" /> tag,'
        ' or pass clientId when initializing GoogleSignIn');

    assert(params.serverClientId == null,
        'serverClientId is not supported on Web.');

    assert(
        !params.scopes.any((String scope) => scope.contains(' ')),
        "OAuth 2.0 Scopes for Google APIs can't contain spaces. "
        'Check https://developers.google.com/identity/protocols/googlescopes '
        'for a list of valid OAuth 2.0 scopes.');

    await _isGapiInitialized;

    final auth2.GoogleAuth auth = auth2.init(auth2.ClientConfig(
      hosted_domain: params.hostedDomain,
      // The js lib wants a space-separated list of values
      scope: params.scopes.join(' '),
      client_id: appClientId!,
      plugin_name: 'dart-google_sign_in_web',
    ));

    final Completer<void> isAuthInitialized = Completer<void>();
    _isAuthInitialized = isAuthInitialized.future;
    _isInitCalled = true;

    auth.then(allowInterop((auth2.GoogleAuth initializedAuth) {
      // onSuccess

      // TODO(ditman): https://github.com/flutter/flutter/issues/48528
      // This plugin doesn't notify the app of external changes to the
      // state of the authentication, i.e: if you logout elsewhere...

      isAuthInitialized.complete();
    }), allowInterop((auth2.GoogleAuthInitFailureError reason) {
      // onError
      isAuthInitialized.completeError(PlatformException(
        code: reason.error,
        message: reason.details,
        details:
            'https://developers.google.com/identity/sign-in/web/reference#error_codes',
      ));
    }));

    return _isAuthInitialized;
  }

  @override
  Future<GoogleSignInUserData?> signInSilently() async {
    await initialized;

    return gapiUserToPluginUserData(
        auth2.getAuthInstance()?.currentUser?.get());
  }

  @override
  Future<GoogleSignInUserData?> signIn() async {
    await initialized;
    try {
      return gapiUserToPluginUserData(await auth2.getAuthInstance()?.signIn());
    } on auth2.GoogleAuthSignInError catch (reason) {
      throw PlatformException(
        code: reason.error,
        message: 'Exception raised from GoogleAuth.signIn()',
        details:
            'https://developers.google.com/identity/sign-in/web/reference#error_codes_2',
      );
    }
  }

  @override
  Future<GoogleSignInTokenData> getTokens(
      {required String email, bool? shouldRecoverAuth}) async {
    await initialized;

    final auth2.GoogleUser? currentUser =
        auth2.getAuthInstance()?.currentUser?.get();
    final auth2.AuthResponse? response = currentUser?.getAuthResponse();

    return GoogleSignInTokenData(
        idToken: response?.id_token, accessToken: response?.access_token);
  }

  @override
  Future<void> signOut() async {
    await initialized;

    return auth2.getAuthInstance()?.signOut();
  }

  @override
  Future<void> disconnect() async {
    await initialized;

    final auth2.GoogleUser? currentUser =
        auth2.getAuthInstance()?.currentUser?.get();

    if (currentUser == null) {
      return;
    }

    return currentUser.disconnect();
  }

  @override
  Future<bool> isSignedIn() async {
    await initialized;

    final auth2.GoogleUser? currentUser =
        auth2.getAuthInstance()?.currentUser?.get();

    if (currentUser == null) {
      return false;
    }

    return currentUser.isSignedIn();
  }

  @override
  Future<void> clearAuthCache({required String token}) async {
    await initialized;

    return auth2.getAuthInstance()?.disconnect();
  }

  @override
  Future<bool> requestScopes(List<String> scopes) async {
    await initialized;

    final auth2.GoogleUser? currentUser =
        auth2.getAuthInstance()?.currentUser?.get();

    if (currentUser == null) {
      return false;
    }

    final String grantedScopes = currentUser.getGrantedScopes() ?? '';
    final Iterable<String> missingScopes =
        scopes.where((String scope) => !grantedScopes.contains(scope));

    if (missingScopes.isEmpty) {
      return true;
    }

    final Object? response = await currentUser
        .grant(auth2.SigninOptions(scope: missingScopes.join(' ')));

    return response != null;
  }
}
