import 'dart:async';

import 'package:flutter/material.dart';

import '../di/injector.dart';
import '../services/unread_service.dart';
import 'theme.dart';

/// Wraps [child] with a small live unread-count badge. It listens to the
/// app-wide [UnreadService] and rebuilds whenever a count changes: on a new
/// message, or when a chat is opened (marked read). Shows the total across all
/// conversations, or — when [peer] is set — just that peer's count.
///
/// When no unread tracker is available (widget tests, inventory-only builds) or
/// the count is zero, it renders [child] unadorned. Positioning is via Flutter's
/// [Badge], which is directional (top-`end`), so it's correct under RTL.
class UnreadBadge extends StatefulWidget {
  const UnreadBadge({
    required this.child,
    this.peer,
    this.service,
    super.key,
  });

  final Widget child;

  /// A specific conversation's count; null means the app-wide total.
  final String? peer;

  /// Overrides the [UnreadService] lookup (for tests). Falls back to `getIt`.
  final UnreadService? service;

  @override
  State<UnreadBadge> createState() => _UnreadBadgeState();
}

class _UnreadBadgeState extends State<UnreadBadge> {
  UnreadService? _service;
  StreamSubscription<void>? _sub;
  int _count = 0;

  @override
  void initState() {
    super.initState();
    _service = widget.service ??
        (getIt.isRegistered<UnreadService>() ? getIt<UnreadService>() : null);
    final service = _service;
    if (service != null) {
      _refresh();
      _sub = service.changes.listen((_) => _refresh());
    }
  }

  @override
  void didUpdateWidget(UnreadBadge old) {
    super.didUpdateWidget(old);
    // A recycled row may now point at a different peer.
    if (old.peer != widget.peer) _refresh();
  }

  Future<void> _refresh() async {
    final service = _service;
    if (service == null) return;
    final peer = widget.peer;
    final count = peer == null
        ? await service.totalUnreadCount()
        : await service.unreadCount(peer);
    if (mounted) setState(() => _count = count);
  }

  @override
  void dispose() {
    _sub?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Badge(
      isLabelVisible: _count > 0,
      label: Text('$_count'),
      backgroundColor: seedGreen,
      child: widget.child,
    );
  }
}
