import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'core/api/api_client_provider.dart';
import 'core/auth/auth_notifier.dart';
import 'core/chat/mitra_chat_notifier.dart';
import 'core/status/status_notifier.dart';
import 'core/chat/chat_request_notifier.dart';
import 'core/chat/widgets/chat_request_overlay.dart';
import 'core/notifications/notification_service.dart';
import 'core/theme/halo_theme.dart';
import 'firebase_options.dart';
import 'router.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  final messaging = FirebaseMessaging.instance;
  await messaging.requestPermission();

  runApp(const ProviderScope(child: App()));
}

class App extends ConsumerStatefulWidget {
  const App({super.key});

  @override
  ConsumerState<App> createState() => _AppState();
}

class _AppState extends ConsumerState<App> with WidgetsBindingObserver {
  bool _fcmRegistered = false;
  // Session the chat WS was on at the moment we backgrounded. Restored on
  // resume so a backgrounded mitra reconnects to the same chat once they
  // foreground the app. Mirrors the customer-app fix (main.dart on the
  // client side) — backend's sendMessage checks recipient WS readyState
  // before falling back to FCM, so leaving the WS open while paused makes
  // FCM never fire and the mitra misses customer messages in background.
  String? _pausedChatSessionId;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.paused || state == AppLifecycleState.detached) {
      ref.read(onlineStatusProvider.notifier).onAppPaused();
      // Close the chat WS so backend `sendMessage` falls back to FCM when
      // the customer sends a message. Stash the active session_id so we
      // can rejoin it on resume.
      final chatNotifier = ref.read(mitraChatProvider.notifier);
      final sid = chatNotifier.connectedSessionId;
      if (sid != null) {
        _pausedChatSessionId = sid;
        chatNotifier.disconnect();
      }
    } else if (state == AppLifecycleState.resumed) {
      ref.read(onlineStatusProvider.notifier).onAppResumed();
      // Reconnect to the chat we backgrounded out of, if any.
      final saved = _pausedChatSessionId;
      _pausedChatSessionId = null;
      if (saved != null) {
        // ignore: discarded_futures
        ref.read(mitraChatProvider.notifier).connect(saved);
      }
    }
  }

  void _registerFcmToken() {
    if (_fcmRegistered) return;
    _fcmRegistered = true;
    Future(() async {
      try {
        final token = await FirebaseMessaging.instance.getToken();
        if (token != null) {
          await ref.read(apiClientProvider).post('/api/shared/device-token', data: {'token': token});
        }
      } catch (_) {
        _fcmRegistered = false;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    // Listen for auth changes to load status and register FCM
    ref.listen(mitraAuthProvider, (prev, next) {
      final data = next.valueOrNull;
      if (data is MitraAuthAuthenticatedData) {
        ref.read(onlineStatusProvider.notifier).load();
        _registerFcmToken();
      }
    });

    final router = ref.watch(routerProvider);
    NotificationService.initialize(router);
    NotificationService.onChatRequestTapped = (sessionId) {
      ref.read(chatRequestProvider.notifier).setIncomingFromNotification(sessionId);
    };

    return ChatRequestOverlay(
      child: MaterialApp.router(
        title: 'Halo Bestie Mitra',
        theme: haloThemeData(),
        routerConfig: router,
      ),
    );
  }
}
