import 'dart:developer' as developer;
import 'package:flutter_bloc/flutter_bloc.dart';

/// Global BLoC observer for centralized logging and monitoring.
///
/// This observer provides visibility into all BLoC lifecycle events across
/// the entire application, enabling centralized logging, debugging, and
/// error monitoring.
///
/// **Features:**
/// - Logs BLoC creation and disposal
/// - Logs all events and state changes
/// - Captures and logs errors with stack traces
/// - Ready for integration with monitoring services (Sentry, Firebase Crashlytics)
///
/// **Setup:**
/// Register this observer in your app's main.dart before runApp():
/// ```dart
/// void main() {
///   Bloc.observer = CoreBlocObserver();
///   runApp(MyApp());
/// }
/// ```
class CoreBlocObserver extends BlocObserver {
  /// Whether to log state changes (can be verbose in production)
  final bool logStateChanges;

  /// Whether to log events
  final bool logEvents;

  CoreBlocObserver({
    this.logStateChanges = false,
    this.logEvents = true,
  });

  @override
  void onCreate(BlocBase bloc) {
    super.onCreate(bloc);
    developer.log(
      'Created: ${bloc.runtimeType}',
      name: 'BlocObserver',
    );
  }

  @override
  void onEvent(Bloc bloc, Object? event) {
    super.onEvent(bloc, event);
    if (logEvents) {
      developer.log(
        'Event: ${event.runtimeType}',
        name: bloc.runtimeType.toString(),
      );
    }
  }

  @override
  void onChange(BlocBase bloc, Change change) {
    super.onChange(bloc, change);
    if (logStateChanges) {
      developer.log(
        'State: ${change.currentState.runtimeType} → ${change.nextState.runtimeType}',
        name: bloc.runtimeType.toString(),
      );
    }
  }

  @override
  void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
    super.onError(bloc, error, stackTrace);
    
    // Log error to console
    developer.log(
      'ERROR in ${bloc.runtimeType}',
      name: 'BlocObserver',
      error: error,
      stackTrace: stackTrace,
    );

    // TODO: Send to monitoring service
    // Example integrations:
    // 
    // Sentry:
    // Sentry.captureException(
    //   error,
    //   stackTrace: stackTrace,
    //   hint: Hint.withMap({'bloc': bloc.runtimeType.toString()}),
    // );
    //
    // Firebase Crashlytics:
    // FirebaseCrashlytics.instance.recordError(
    //   error,
    //   stackTrace,
    //   reason: 'BLoC Error in ${bloc.runtimeType}',
    // );
  }

  @override
  void onClose(BlocBase bloc) {
    super.onClose(bloc);
    developer.log(
      'Closed: ${bloc.runtimeType}',
      name: 'BlocObserver',
    );
  }

  @override
  void onTransition(Bloc bloc, Transition transition) {
    super.onTransition(bloc, transition);
    if (logStateChanges) {
      developer.log(
        'Transition: ${transition.event.runtimeType} → ${transition.nextState.runtimeType}',
        name: bloc.runtimeType.toString(),
      );
    }
  }
}
