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/active_session_notifier.dart';
import 'core/chat/chat_notifier.dart';
import 'core/notifications/notification_service.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> {
  bool _fcmRegistered = false;

  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) {
    // FCM registration on auth.
    ref.listen(authProvider, (prev, next) {
      final data = next.valueOrNull;
      if (data is AuthAuthenticatedData || data is AuthAnonymousData) {
        _registerFcmToken();
      } else {
        // Logged out (or initial) — ensure the chat WS is closed.
        ref.read(chatProvider.notifier).disconnect();
      }
    });

    // Global chat WebSocket lifecycle: connect whenever the user has an
    // active session, regardless of which screen is mounted. The chat screen
    // only joins this connection — it doesn't own it. FCM remains the
    // background-only fallback.
    ref.listen(activeSessionProvider, (prev, next) {
      final snapshot = next.valueOrNull;
      final notifier = ref.read(chatProvider.notifier);
      if (snapshot == null || !snapshot.hasSession) {
        if (notifier.connectedSessionId != null) {
          notifier.disconnect();
        }
        return;
      }
      final sessionId = snapshot.sessionId;
      if (sessionId != null && notifier.connectedSessionId != sessionId) {
        notifier.connectIfNotConnected(sessionId);
      }
    });

    final router = ref.watch(routerProvider);

    NotificationService.initialize(router);

    return MaterialApp.router(
      title: 'Halo Bestie',
      routerConfig: router,
    );
  }
}
