@TestOn('browser')
import 'dart:async';

import 'package:test/test.dart';
import 'package:proto_socket/proto_socket.dart';

const _host = '127.0.0.1';
const _wsPath = '/';
const _heartbeatIntervalSeconds = 30;
const _heartbeatWaitSeconds = 10;

class _BrowserWsClient extends WsProtobufClient {
  _BrowserWsClient(dynamic ws)
      : super(ws, _heartbeatIntervalSeconds, _heartbeatWaitSeconds, {
          TestData.getDefault().info_.qualifiedMessageName: TestData.fromBuffer,
        });
}

void registerBrowserWsTests({
  required String serverLabel,
  required int port,
  required String serverPushMessage,
  bool secure = false,
}) {
  final transportLabel = secure ? 'WSS' : 'WS';

  group(
      'Dart Web WsProtobufClient talks to $serverLabel $transportLabel server',
      () {
    test('send-push: fire-and-forget and receive push', () async {
      final ws = secure
          ? await WsProtobufClient.connectSecure(_host, port, path: _wsPath)
          : await WsProtobufClient.connect(_host, port, path: _wsPath);
      final client = _BrowserWsClient(ws);

      final pushCompleter = Completer<TestData>();
      client.addListener<TestData>((data) {
        if (!pushCompleter.isCompleted) {
          pushCompleter.complete(data);
        }
      });

      await client.send(TestData()
        ..index = 101
        ..message = 'fire from dart web client');

      final push =
          await pushCompleter.future.timeout(const Duration(seconds: 5));
      expect(push.index, equals(200));
      expect(push.message, equals(serverPushMessage));

      await client.close();
    });

    test('request-response: single and concurrent requests', () async {
      final ws = secure
          ? await WsProtobufClient.connectSecure(_host, port, path: _wsPath)
          : await WsProtobufClient.connect(_host, port, path: _wsPath);
      final client = _BrowserWsClient(ws);

      final single = await client
          .sendRequest<TestData, TestData>(TestData()
            ..index = 21
            ..message = 'single request from dart web')
          .timeout(const Duration(seconds: 5));
      expect(single.index, equals(42));
      expect(single.message, equals('echo: single request from dart web'));

      final futures = <Future<void>>[];
      for (var i = 0; i < 5; i++) {
        futures.add(() async {
          final index = 30 + i;
          final message = 'multi request $i from dart web';
          final res = await client
              .sendRequest<TestData, TestData>(TestData()
                ..index = index
                ..message = message)
              .timeout(const Duration(seconds: 5));
          expect(res.index, equals(index * 2));
          expect(res.message, equals('echo: $message'));
        }());
      }
      await Future.wait(futures);

      await client.close();
    });
  });
}
