import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../domain/usecases/get_default_locale_use_case.dart';
import '../domain/usecases/get_locale_use_case.dart';
import '../domain/usecases/get_supported_locales_use_case.dart';
import '../domain/usecases/set_locale_use_case.dart';
import '../l10n/strings.g.dart';
import 'locale_event.dart';
import 'locale_state.dart';

/// A [Bloc] that manages the application's locale state.
///
/// It coordinates the flow between user language requests and persistent storage
/// using [SetLocaleUseCase] and [GetLocaleUseCase].
class LocaleBloc extends Bloc<LocaleEvent, LocaleState> {
  /// Creates a [LocaleBloc] with the required use cases.
  LocaleBloc({
    required this.getLocaleUseCase,
    required this.setLocaleUseCase,
    required this.getSupportedLocalesUseCase,
    required this.getDefaultLocaleUseCase,
  }) : super(LocaleState.initial()) {
    on<ChangeLocale>(_onChangeLocale);
    on<LoadLocale>(_onLoadLocale);

    /// Initial event
    add(const LoadLocale());
  }

  /// Use case for retrieving the saved locale.
  final GetLocaleUseCase getLocaleUseCase;

  /// Use case for saving the selected locale.
  final SetLocaleUseCase setLocaleUseCase;

  /// Use case for retrieving supported locales.
  final GetSupportedLocalesUseCase getSupportedLocalesUseCase;

  /// Use case for retrieving the default locale.
  final GetDefaultLocaleUseCase getDefaultLocaleUseCase;

  /// Handles the [ChangeLocale] event by saving it via the use case and emitting new state.
  Future<void> _onChangeLocale(
    ChangeLocale event,
    Emitter<LocaleState> emit,
  ) async {
    // 1. Update slang settings
    await LocaleSettings.setLocaleRaw(event.locale.languageCode);

    // 2. Persist using Use Case
    await setLocaleUseCase(event.locale);
 
    // 3. Emit new state
    emit(
      LocaleState(
        locale: event.locale,
        supportedLocales: state.supportedLocales,
      ),
    );
  }

  /// Handles the [LoadLocale] event by retrieving it via the use case and updating settings.
  Future<void> _onLoadLocale(
    LoadLocale event,
    Emitter<LocaleState> emit,
  ) async {
    final Locale savedLocale = await getLocaleUseCase();
    final List<Locale> supportedLocales = getSupportedLocalesUseCase();

    await LocaleSettings.setLocaleRaw(savedLocale.languageCode);

    emit(LocaleState(
      locale: savedLocale,
      supportedLocales: supportedLocales,
    ));
  }
}
