import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';

typedef OnDataReceived = void Function(String soil, String humidity,
    String temperature, String intensity, String batLevel);

class MQTTManager {
  final String serverUri;
  final String clientId;
  final OnDataReceived onDataReceived;
  late MqttServerClient _client;

  MQTTManager({
    required this.serverUri,
    required this.clientId,
    required this.onDataReceived,
  }) {
    _client = MqttServerClient(serverUri, clientId);
    _client.port = 1883;
    _client.keepAlivePeriod = 20;
    _client.onDisconnected = onDisconnected;
    _client.onConnected = onConnected;
    _client.onSubscribed = onSubscribed;
    _client.onUnsubscribed = onUnsubscribed;
    _client.pongCallback = pong;
  }

  Future<void> connect() async {
    try {
      print('MQTT client connecting...');
      final MqttClientConnectionStatus? status = await _client.connect();
      if (status?.state == MqttConnectionState.connected) {
        print('MQTT client connected');
      } else {
        print(
            'MQTT client connection failed - disconnecting, state is ${status?.state}');
        _client.disconnect();
      }
    } catch (e) {
      print('Exception: $e');
      _client.disconnect();
    }

    _client.updates?.listen((List<MqttReceivedMessage<MqttMessage>> c) {
      final MqttPublishMessage recMess = c[0].payload as MqttPublishMessage;
      final String message =
          MqttPublishPayload.bytesToStringAsString(recMess.payload.message);

      // Assuming the message payload is a comma-separated string
      final parts = message.split(',');
      if (parts.length == 5) {
        final soil = _extractNumericValue(parts[0]);
        final humidity = _extractNumericValue(parts[1]);
        final temperature = _extractNumericValue(parts[2]);
        final intensity = _extractNumericValue(parts[3]);
        final batLevel = _extractNumericValue(parts[4]);

        onDataReceived(soil, humidity, temperature, intensity, batLevel);
      }
    });
  }

  void disconnect() {
    print('MQTT client disconnecting...');
    _client.disconnect();
  }

  void onDisconnected() {
    print('MQTT client disconnected');
  }

  void onConnected() {
    print('MQTT client connected');
    _client.subscribe('outTopic', MqttQos.atMostOnce);
  }

  void onSubscribed(String topic) {
    print('Subscribed to topic: $topic');
  }

  void onUnsubscribed(String? topic) {
    print('Unsubscribed from topic: $topic');
  }

  void pong() {
    print('Ping response client callback invoked');
  }

  String _extractNumericValue(String input) {
    final numericValue =
        RegExp(r'\d+\.*\d*').allMatches(input).map((m) => m.group(0)).join('');
    return numericValue.isEmpty ? '0' : numericValue;
  }

  void publishMessage(String topic, String message) {
    final MqttClientPayloadBuilder builder = MqttClientPayloadBuilder();
    builder.addString(message);
    _client.publishMessage(topic, MqttQos.exactlyOnce, builder.payload!);
  }
}
