// Copyright 2019 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:io';

import 'package:cocoon_service/src/model/appengine/allowed_account.dart';
import 'package:cocoon_service/src/model/google/token_info.dart';
import 'package:cocoon_service/src/request_handling/authentication.dart';
import 'package:cocoon_service/src/request_handling/exceptions.dart';
import 'package:cocoon_service/src/service/logging.dart';
import 'package:http/http.dart' as http;
import 'package:http/testing.dart';
import 'package:logging/logging.dart';
import 'package:test/test.dart';

import '../src/datastore/fake_config.dart';
import '../src/request_handling/fake_authentication.dart';
import '../src/request_handling/fake_http.dart';

void main() {
  group('AuthenticationProvider', () {
    late FakeConfig config;
    late FakeClientContext clientContext;
    late FakeHttpRequest request;
    late AuthenticationProvider auth;
    late TokenInfo token;

    setUp(() {
      config = FakeConfig();
      token = TokenInfo(email: 'abc123@gmail.com', issued: DateTime.now());
      clientContext = FakeClientContext();
      request = FakeHttpRequest();
      auth = AuthenticationProvider(
        config: config,
        clientContextProvider: () => clientContext,
        httpClientProvider: () => throw AssertionError(),
      );
    });

    test('throws Unauthenticated with no auth headers', () async {
      expect(auth.authenticate(request), throwsA(isA<Unauthenticated>()));
    });

    test('succeeds for App Engine cronjobs', () async {
      request.headers.set('X-Appengine-Cron', 'true');
      final AuthenticatedContext result = await auth.authenticate(request);
      expect(result.clientContext, same(clientContext));
    });

    group('when id token is given', () {
      late MockClient httpClient;

      setUp(() {
        auth = AuthenticationProvider(
          config: config,
          clientContextProvider: () => clientContext,
          httpClientProvider: () => httpClient,
        );
      });

      test('auth succeeds with authenticated header', () async {
        httpClient = MockClient((_) async => http.Response('{"aud": "client-id", "hd": "google.com"}', HttpStatus.ok));
        auth = AuthenticationProvider(
          config: config,
          clientContextProvider: () => clientContext,
          httpClientProvider: () => httpClient,
        );
        config.oauthClientIdValue = 'client-id';
        request.headers.add('X-Flutter-IdToken', 'authenticated');
        final AuthenticatedContext result = await auth.authenticate(request);
        expect(result.clientContext, same(clientContext));
        expect(result, isNotNull);
      });

      test('fails if token verification fails', () async {
        config.oauthClientIdValue = 'client-id';
        request.headers.add('X-Flutter-IdToken', 'authenticated');
        await expectLater(
          auth.authenticateToken(
            token,
            clientContext: FakeClientContext(),
          ),
          throwsA(isA<Unauthenticated>()),
        );
      });

      test('fails if tokenInfo returns invalid JSON', () async {
        httpClient = MockClient((_) async => http.Response('Not JSON!', HttpStatus.ok));
        final List<LogRecord> records = <LogRecord>[];
        log.onRecord.listen((LogRecord record) => records.add(record));
        await expectLater(auth.tokenInfo(request), throwsA(isA<InternalServerError>()));
        expect(records, isEmpty);
      });

      test('fails if token verification yields forged token', () async {
        final TokenInfo token = TokenInfo(
          audience: 'forgery',
          email: 'abc@abc.com',
          issued: DateTime.now(),
        );
        config.oauthClientIdValue = 'expected-client-id';
        await expectLater(
          auth.authenticateToken(
            token,
            clientContext: FakeClientContext(),
          ),
          throwsA(isA<Unauthenticated>()),
        );
      });

      test('allows different aud for gcloud tokens with google accounts', () async {
        final TokenInfo token = TokenInfo(
          audience: 'different',
          email: 'abc@google.com',
          issued: DateTime.now(),
        );
        config.oauthClientIdValue = 'expected-client-id';
        await expectLater(
          auth.authenticateToken(
            token,
            clientContext: FakeClientContext(),
          ),
          throwsA(isA<Unauthenticated>()),
        );
      });

      test('succeeds for google.com auth user', () async {
        final TokenInfo token = TokenInfo(
          audience: 'client-id',
          hostedDomain: 'google.com',
          email: 'abc@google.com',
          issued: DateTime.now(),
        );
        config.oauthClientIdValue = 'client-id';
        final AuthenticatedContext result = await auth.authenticateToken(
          token,
          clientContext: clientContext,
        );
        expect(result.clientContext, same(clientContext));
      });

      test('fails for non-allowed non-Google auth users', () async {
        final TokenInfo token =
            TokenInfo(audience: 'client-id', hostedDomain: 'gmail.com', email: 'abc@gmail.com', issued: DateTime.now());
        config.oauthClientIdValue = 'client-id';
        await expectLater(
          auth.authenticateToken(
            token,
            clientContext: FakeClientContext(),
          ),
          throwsA(isA<Unauthenticated>()),
        );
      });

      test('succeeds for allowed non-Google auth users', () async {
        final AllowedAccount account = AllowedAccount(
          key: config.db.emptyKey.append<int>(AllowedAccount, id: 123),
          email: 'test@gmail.com',
        );
        config.db.values[account.key] = account;
        final TokenInfo token = TokenInfo(
          audience: 'client-id',
          email: 'test@gmail.com',
          issued: DateTime.now(),
        );
        config.oauthClientIdValue = 'client-id';
        final AuthenticatedContext result = await auth.authenticateToken(token, clientContext: clientContext);
        expect(result.clientContext, same(clientContext));
      });
    });
  });
}
