// 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:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:cocoon_service/src/model/luci/push_message.dart';
import 'package:cocoon_service/src/request_handling/body.dart';
import 'package:cocoon_service/src/request_handling/exceptions.dart';
import 'package:cocoon_service/src/request_handling/subscription_handler.dart';
import 'package:cocoon_service/src/service/cache_service.dart';
import 'package:gcloud/service_scope.dart' as ss;
import 'package:test/test.dart';

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

void main() {
  group('Subscription', () {
    late HttpServer server;
    late SubscriptionHandler subscription;

    const PushMessageEnvelope testEnvelope = PushMessageEnvelope(
      message: PushMessage(
        data: 'test',
        messageId: '123',
      ),
      subscription: 'https://flutter-dashboard.appspot.com/api/luci-status-handler',
    );

    setUp(() async {
      server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
      server.listen((HttpRequest request) {
        runZoned<dynamic>(
          () {
            return ss.fork(() {
              return subscription.service(request);
            });
          },
        );
      });
    });

    tearDown(() async {
      await server.close();
    });

    Future<HttpClientResponse> issueRequest({String? body}) async {
      final HttpClient client = HttpClient();
      final Uri url = Uri(scheme: 'http', host: 'localhost', port: server.port, path: '/path');
      final HttpClientRequest request = await client.getUrl(url);
      if (body != null) {
        request.contentLength = body.length;
        request.write(body);
        await request.flush();
      }
      return await request.close();
    }

    test('failed authentication yields HTTP unauthorized', () async {
      subscription = UnauthTest();
      final HttpClientResponse response = await issueRequest();
      expect(response.statusCode, HttpStatus.unauthorized);
      expect(await utf8.decoder.bind(response).join(), 'Not authenticated');
    });

    test('passed authentication yields empty body', () async {
      subscription = AuthTest();
      final HttpClientResponse response = await issueRequest(body: jsonEncode(testEnvelope));
      expect(response.statusCode, HttpStatus.ok);
    });

    test('pubsub message is parsed', () async {
      subscription = ReadMessageTest();
      final HttpClientResponse response = await issueRequest(body: jsonEncode(testEnvelope));
      expect(response.statusCode, HttpStatus.ok);
      final String responseBody = String.fromCharCodes((await response.toList()).first);
      expect(responseBody, 'test');
    });

    test('ensure message ids are idempotent', () async {
      final CacheService cache = CacheService(inMemory: true);
      subscription = ReadMessageTest(cache);
      HttpClientResponse response = await issueRequest(body: jsonEncode(testEnvelope));
      String responseBody = String.fromCharCodes((await response.toList()).first);
      expect(response.statusCode, HttpStatus.ok);
      // 1. Expected message for this was processed
      expect(responseBody, 'test');

      response = await issueRequest(body: jsonEncode(testEnvelope));
      responseBody = String.fromCharCodes((await response.toList()).first);
      expect(response.statusCode, HttpStatus.ok);
      // 2. Empty message is returned as this was already processed
      expect(responseBody, '123 was already processed');
      expect(await cache.getOrCreate(subscription.subscriptionName, '123', createFn: null), isNotNull);
    });

    test('ensure messages can be retried', () async {
      final CacheService cache = CacheService(inMemory: true);
      subscription = ErrorTest(cache);
      HttpClientResponse response = await issueRequest(body: jsonEncode(testEnvelope));
      Uint8List? messageLock = await cache.getOrCreate('error', '123', createFn: null);
      expect(response.statusCode, HttpStatus.internalServerError);
      expect(messageLock, isNull);

      response = await issueRequest(body: jsonEncode(testEnvelope));
      messageLock = await cache.getOrCreate('error', '123', createFn: null);
      expect(response.statusCode, HttpStatus.internalServerError);
      expect(messageLock, isNull);
    });
  });
}

/// Test stub of [SubscriptionHandler] to validate unauthenticated requests.
class UnauthTest extends SubscriptionHandler {
  UnauthTest()
      : super(
          cache: CacheService(inMemory: true),
          config: FakeConfig(),
          authProvider: FakeAuthenticationProvider(authenticated: false),
          subscriptionName: 'unauth',
        );

  @override
  Future<Body> get() async => throw StateError('Unreachable');
}

/// Test stub of [SubscriptionHandler] to validate authenticated requests.
class AuthTest extends SubscriptionHandler {
  AuthTest()
      : super(
          cache: CacheService(inMemory: true),
          config: FakeConfig(),
          authProvider: FakeAuthenticationProvider(),
          subscriptionName: 'auth',
        );

  @override
  Future<Body> get() async => Body.empty;
}

/// Test stub of [SubscriptionHandler] to validate push messages can be read.
class ErrorTest extends SubscriptionHandler {
  ErrorTest([CacheService? cache])
      : super(
          cache: cache ?? CacheService(inMemory: true),
          config: FakeConfig(),
          authProvider: FakeAuthenticationProvider(),
          subscriptionName: 'error',
        );

  @override
  Future<Body> get() async => throw const InternalServerError('Test error!');
}

/// Test stub of [SubscriptionHandler] to validate push messages can be read.
class ReadMessageTest extends SubscriptionHandler {
  ReadMessageTest([CacheService? cache])
      : super(
          cache: cache ?? CacheService(inMemory: true),
          config: FakeConfig(),
          authProvider: FakeAuthenticationProvider(),
          subscriptionName: 'read',
        );

  @override
  Future<Body> get() async => Body.forString(message.data!);
}
