import 'dart:async';

import 'package:signalr_netcore/signalr_client.dart';

import '../api/api_config.dart';

/// Events broadcast from the KDS hub.
class HubNotification {
  const HubNotification({
    required this.id,
    required this.type,
    required this.title,
    this.body,
    this.tableNumber,
    this.referenceId,
    required this.createdAt,
  });

  final String id;
  final String type;
  final String title;
  final String? body;
  final String? tableNumber;
  final String? referenceId;
  final DateTime createdAt;

  factory HubNotification.fromMap(Map<String, dynamic> m) => HubNotification(
        id: (m['id'] ?? '') as String,
        type: (m['type'] ?? '') as String,
        title: (m['title'] ?? '') as String,
        body: m['body'] as String?,
        tableNumber: m['tableNumber'] as String?,
        referenceId: m['referenceId'] as String?,
        createdAt: DateTime.tryParse(m['createdAt'] as String? ?? '') ??
            DateTime.now(),
      );
}

class WaiterHubClient {
  WaiterHubClient({required this.cafeId, required this.accessToken});

  final String cafeId;
  final String accessToken;

  HubConnection? _connection;

  final _notificationController =
      StreamController<HubNotification>.broadcast();

  Stream<HubNotification> get notifications => _notificationController.stream;

  bool get isConnected =>
      _connection?.state == HubConnectionState.Connected;

  Future<void> connect() async {
    final hubUrl = '$apiBaseUrl/hubs/kds';

    _connection = HubConnectionBuilder()
        .withUrl(
          hubUrl,
          options: HttpConnectionOptions(
            accessTokenFactory: () async => accessToken,
            skipNegotiation: false,
          ),
        )
        .withAutomaticReconnect()
        .build();

    _connection!.on('NotificationReceived', _onNotification);

    _connection!.onclose(({error}) async {
      // Auto-reconnect handled by withAutomaticReconnect
    });

    try {
      await _connection!.start();
      await _connection!.invoke('JoinCafe', args: [cafeId]);
    } catch (_) {
      // Will retry via automatic reconnect
    }
  }

  void _onNotification(List<Object?>? args) {
    if (args == null || args.isEmpty) return;
    final raw = args[0];
    if (raw is! Map) return;
    final m = Map<String, dynamic>.from(raw);
    _notificationController.add(HubNotification.fromMap(m));
  }

  Future<void> dispose() async {
    await _connection?.stop();
    await _notificationController.close();
  }
}
