import 'dart:async';

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../core/api/api_client.dart';
import '../../core/auth/auth_provider.dart';
import '../../core/hub/hub_provider.dart';
import 'waiter_notification.dart';

// ── Local notification setup ────────────────────────────────────────────────
final _localNotifications = FlutterLocalNotificationsPlugin();

Future<void> initLocalNotifications() async {
  const android = AndroidInitializationSettings('@mipmap/ic_launcher');
  const ios = DarwinInitializationSettings(
    requestAlertPermission: true,
    requestBadgePermission: true,
    requestSoundPermission: true,
  );
  await _localNotifications.initialize(
    const InitializationSettings(android: android, iOS: ios),
  );
}

Future<void> _showLocalNotification(WaiterNotification n) async {
  const android = AndroidNotificationDetails(
    'meezi_waiter_channel',
    'میزی — گارسون',
    channelDescription: 'اعلان‌های میزی برای گارسون',
    importance: Importance.max,
    priority: Priority.high,
    playSound: true,
  );
  const ios = DarwinNotificationDetails(presentSound: true, presentAlert: true);
  await _localNotifications.show(
    n.createdAt.millisecondsSinceEpoch ~/ 1000,
    n.title,
    n.body,
    const NotificationDetails(android: android, iOS: ios),
  );
}

// ── Notification state ───────────────────────────────────────────────────────
class NotificationState {
  const NotificationState({
    this.items = const [],
    this.isLoading = false,
  });

  final List<WaiterNotification> items;
  final bool isLoading;

  int get unreadCount => items.where((n) => !n.isRead).length;

  NotificationState copyWith({
    List<WaiterNotification>? items,
    bool? isLoading,
  }) =>
      NotificationState(
        items: items ?? this.items,
        isLoading: isLoading ?? this.isLoading,
      );
}

final notificationProvider =
    StateNotifierProvider<NotificationNotifier, NotificationState>((ref) {
  final notifier = NotificationNotifier(ref);
  notifier._init();
  return notifier;
});

class NotificationNotifier extends StateNotifier<NotificationState> {
  NotificationNotifier(this._ref) : super(const NotificationState());

  final Ref _ref;
  StreamSubscription<dynamic>? _hubSub;

  void _init() {
    _fetchFromApi();
    _subscribeHub();
  }

  void _subscribeHub() {
    _hubSub?.cancel();
    final hub = _ref.read(hubClientProvider);
    if (hub == null) return;

    _hubSub = hub.notifications.listen((event) {
      final n = WaiterNotification.fromHub(event);
      state = state.copyWith(items: [n, ...state.items]);
      _showLocalNotification(n);
    });
  }

  Future<void> _fetchFromApi() async {
    final session = _ref.read(authProvider);
    if (session == null) return;
    state = state.copyWith(isLoading: true);
    try {
      final client = _ref.read(apiClientProvider);
      final res = await client.dio.get<Map<String, dynamic>>(
        '/api/cafes/${session.cafeId}/notifications',
        queryParameters: {'limit': 50},
      );
      final raw = res.data?['data'] as List?;
      final items = raw
              ?.map((e) =>
                  WaiterNotification.fromJson(Map<String, dynamic>.from(e as Map)))
              .toList() ??
          [];
      state = state.copyWith(items: items, isLoading: false);
    } catch (_) {
      state = state.copyWith(isLoading: false);
    }
  }

  Future<void> refresh() => _fetchFromApi();

  Future<void> markRead(String id) async {
    final session = _ref.read(authProvider);
    if (session == null) return;
    try {
      final client = _ref.read(apiClientProvider);
      await client.dio.post(
        '/api/cafes/${session.cafeId}/notifications/read',
        data: {'ids': [id]},
      );
    } catch (_) {}
    final updated = state.items.map((n) {
      if (n.id == id) n.isRead = true;
      return n;
    }).toList();
    state = state.copyWith(items: updated);
  }

  Future<void> markAllRead() async {
    final session = _ref.read(authProvider);
    if (session == null) return;
    try {
      final client = _ref.read(apiClientProvider);
      await client.dio.post(
        '/api/cafes/${session.cafeId}/notifications/read',
        data: {'all': true},
      );
    } catch (_) {}
    final updated = state.items.map((n) {
      n.isRead = true;
      return n;
    }).toList();
    state = state.copyWith(items: updated);
  }

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