import 'dart:async';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../api/api_client_provider.dart';

part 'active_session_notifier.g.dart';

/// Snapshot of the current customer's active session (if any) plus its
/// unread-message count. Backed by `/api/client/chat/session/active-with-unread`.
///
/// Lives at app-scope so the home CTA, the global chat WebSocket lifecycle
/// (see `main.dart`), and any badge consumers all share one source of truth.
class ActiveSessionData {
  final Map<String, dynamic>? session;
  final int unreadCount;

  const ActiveSessionData({this.session, this.unreadCount = 0});

  bool get hasSession => session != null;
  String? get sessionId => session?['id'] as String?;
  String get mitraName =>
      (session?['mitra_display_name'] as String?) ?? 'Bestie';

  static const empty = ActiveSessionData();
}

@Riverpod(keepAlive: true)
class ActiveSession extends _$ActiveSession {
  Timer? _pollTimer;

  @override
  Future<ActiveSessionData> build() async {
    ref.onDispose(_stopPolling);
    _startPolling();
    return await _fetch();
  }

  void _startPolling() {
    _stopPolling();
    _pollTimer = Timer.periodic(const Duration(seconds: 15), (_) async {
      try {
        final next = await _fetch();
        state = AsyncData(next);
      } catch (_) {
        // Keep last known state on transient failures.
      }
    });
  }

  void _stopPolling() {
    _pollTimer?.cancel();
    _pollTimer = null;
  }

  Future<ActiveSessionData> _fetch() async {
    final apiClient = ref.read(apiClientProvider);
    final response = await apiClient.get('/api/client/chat/session/active-with-unread');
    final data = response['data'];
    if (data is Map<String, dynamic>) {
      return ActiveSessionData(
        session: data,
        unreadCount: data['unread_count'] as int? ?? 0,
      );
    }
    return ActiveSessionData.empty;
  }

  /// Force a fresh fetch (e.g. on resume, after pairing succeeds, after a
  /// session ends). Updates `state` synchronously to AsyncLoading-with-prev
  /// then to AsyncData.
  Future<void> refresh() async {
    try {
      final next = await _fetch();
      state = AsyncData(next);
    } catch (e, st) {
      state = AsyncError(e, st);
    }
  }

  /// Optimistic local-only update: clear unread without a round-trip
  /// (used after the chat screen marks messages read).
  void markRead() {
    final current = state.valueOrNull;
    if (current == null || !current.hasSession) return;
    state = AsyncData(ActiveSessionData(
      session: current.session,
      unreadCount: 0,
    ));
  }
}
