import 'dart:developer';
import 'dart:io';

import 'package:http/io_client.dart';
import 'package:hmg_qline/constants/app_constants.dart';
import 'package:signalr_core/signalr_core.dart';

abstract class SignalrRepo {
  Future<void> startHubConnection({
    required String deviceIp,
    required Function(List<Object?>?) onHubTicketCall,
    required Function(dynamic) onHubConfigCall,
    required Function(dynamic) onHubConnecting,
    required Function(dynamic) onHubReconnected,
    required Function(dynamic) onHubDisconnected,
  });
}

class SignalrRepoImp implements SignalrRepo {
  HubConnection? connection;

  @override
  Future<void> startHubConnection({
    required String deviceIp,
    required Function(List<Object?>?) onHubTicketCall,
    required Function(dynamic) onHubConfigCall,
    required Function(dynamic) onHubConnecting,
    required Function(dynamic) onHubReconnected,
    required Function(dynamic) onHubDisconnected,
  }) async {
    String hubBaseURL = ApiConstants.baseUrlHub;

    if ((connection != null) && (connection!.state == HubConnectionState.connected || connection!.state == HubConnectionState.connecting)) {
      return;
    }
    connection = HubConnectionBuilder()
        .withUrl(
            "$hubBaseURL?IPAddress=$deviceIp",
            HttpConnectionOptions(
              client: IOClient(HttpClient()..badCertificateCallback = (x, y, z) => true),
              logging: (level, message) => log(message),
            ))
        .withAutomaticReconnect()
        .build();

    connection!.serverTimeoutInMilliseconds = 120000;
    connection!.onclose((exception) {
      log(exception.toString());
      onHubDisconnected(exception);
    });

    connection!.onreconnecting((exception) => onHubConnecting(exception));
    connection!.onreconnected((connectionId) {
      log(connectionId.toString());
      onHubReconnected(connectionId);
    });

    connection!.on(ApiConstants.sendQLinePatientCall, (List<Object?>? message) {
      onHubTicketCall(message);
    });

    connection!.on(ApiConstants.sendQLineConfig, (List<Object?>? message) {
      onHubConfigCall(message);
    });

    await connection!.start();
  }

  bool getHubConnectionState() {
    if (connection == null) return false;
    log("connectionState: ${connection!.state}");
    if (connection!.state == HubConnectionState.connected || connection!.state == HubConnectionState.connecting) return true;
    if (connection!.state == HubConnectionState.disconnected || connection!.state == HubConnectionState.disconnecting) return false;
    return false;
  }

  closeConnection() async {
    if (connection!.state == HubConnectionState.connected || connection!.state == HubConnectionState.connecting) {
      await connection!.stop();
    }
  }
}
