import 'dart:async';
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:iop_client/iop_wire/client_wire_client.dart';
import 'package:iop_client/gen/proto/iop/control.pb.dart';
import 'package:protobuf/protobuf.dart';
import 'package:fixnum/fixnum.dart';

class FakeWebSocket implements WebSocket {
  final _controller = StreamController<dynamic>();

  @override
  StreamSubscription<dynamic> listen(
    void Function(dynamic event)? onData, {
    Function? onError,
    void Function()? onDone,
    bool? cancelOnError,
  }) {
    return _controller.stream.listen(
      onData,
      onError: onError,
      onDone: onDone,
      cancelOnError: cancelOnError,
    );
  }

  @override
  dynamic noSuchMethod(Invocation invocation) {
    return null;
  }
}

class FakeClientWireClient extends ClientWireClient {
  FakeClientWireClient() : super(FakeWebSocket());

  bool helloCalled = false;
  late ClientHelloRequest lastRequest;

  @override
  bool get isAlive => true;

  @override
  Future<Res> sendRequest<
    Req extends GeneratedMessage,
    Res extends GeneratedMessage
  >(Req data, {Duration timeout = const Duration(seconds: 30)}) async {
    if (data is ClientHelloRequest) {
      helloCalled = true;
      lastRequest = data;

      final response = ClientHelloResponse()
        ..ready = true
        ..protocol = 'iop-wire'
        ..serverTimeUnixNano = Int64(123456789)
        ..message = 'Welcome';

      return response as Res;
    }
    throw UnimplementedError();
  }
}

void main() {
  test('ClientWireClient hello request mapping', () async {
    final client = FakeClientWireClient();

    final response = await client.hello(
      clientId: 'client-123',
      clientVersion: '1.0.0',
    );

    expect(client.helloCalled, isTrue);
    expect(client.lastRequest.clientId, equals('client-123'));
    expect(client.lastRequest.clientVersion, equals('1.0.0'));

    expect(response.ready, isTrue);
    expect(response.protocol, equals('iop-wire'));
    expect(response.serverTimeUnixNano, equals(Int64(123456789)));
    expect(response.message, equals('Welcome'));
  });
}
