/// A BLoC (Business Logic Component) that manages account-related state and operations.
///
/// This bloc handles account operations such as loading accounts by user ID,
/// creating new accounts, and managing real-time updates from the account repository.
/// It uses stream subscriptions to listen for account changes and emits corresponding states.
///
/// The bloc supports the following operations:
/// - Loading accounts by user ID with real-time updates
/// - Creating a single account without members
/// - Creating an account with associated members
///
/// All errors are logged using [ErrorService] and emitted as [AccountError] states.
///
/// Example usage:
/// ```dart
/// final accountBloc = AccountBloc(accountRepository);
/// accountBloc.add(LoadAccountsByUserId('user123'));
/// ```
///
/// Remember to close the bloc when done to cancel active subscriptions:
/// ```dart
/// accountBloc.close();
/// ```
library;

import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:travel_mate/services/error_service.dart';
import 'account_event.dart';
import 'account_state.dart';
import '../../repositories/account_repository.dart';
import '../../models/account.dart';

class AccountBloc extends Bloc<AccountEvent, AccountState> {
  final AccountRepository _repository;
  StreamSubscription? _accountsSubscription;
  final _errorService = ErrorService();

  AccountBloc(this._repository) : super(AccountInitial()) {
    on<LoadAccountsByUserId>(_onLoadAccountsByUserId);
    on<_AccountsUpdated>(_onAccountsUpdated);
    on<CreateAccount>(_onCreateAccount);
    on<CreateAccountWithMembers>(_onCreateAccountWithMembers);
    on<AddMemberToAccount>(_onAddMemberToAccount);
    on<RemoveMemberFromAccount>(_onRemoveMemberFromAccount);
  }

  Future<void> _onLoadAccountsByUserId(
    LoadAccountsByUserId event,
    Emitter<AccountState> emit,
  ) async {
    try {
      emit(AccountLoading());
      await _accountsSubscription?.cancel();
      _accountsSubscription = _repository
          .getAccountByUserId(event.userId)
          .listen(
            (accounts) {
              add(_AccountsUpdated(accounts));
            },
            onError: (error) {
              add(_AccountsUpdated([], error: error.toString()));
            },
          );
    } catch (e, stackTrace) {
      _errorService.logError(
        'AccountBloc',
        'Error loading accounts: $e',
        stackTrace,
      );
      emit(const AccountError('Impossible de charger les comptes'));
    }
  }

  Future<void> _onAccountsUpdated(
    _AccountsUpdated event,
    Emitter<AccountState> emit,
  ) async {
    if (event.error != null) {
      _errorService.logError(event.error!, StackTrace.current);
      emit(AccountError(event.error!));
    } else {
      emit(AccountsLoaded(event.accounts));
    }
  }

  Future<void> _onCreateAccount(
    CreateAccount event,
    Emitter<AccountState> emit,
  ) async {
    try {
      emit(AccountLoading());
      final accountId = await _repository.createAccountWithMembers(
        account: event.account,
        members: [],
      );
      emit(AccountOperationSuccess('Compte créé avec succès. ID: $accountId'));
    } catch (e, stackTrace) {
      _errorService.logError(
        'AccountBloc',
        'Error creating account: $e',
        stackTrace,
      );
      emit(const AccountError('Impossible de créer le compte'));
    }
  }

  Future<void> _onCreateAccountWithMembers(
    CreateAccountWithMembers event,
    Emitter<AccountState> emit,
  ) async {
    try {
      emit(AccountLoading());
      final accountId = await _repository.createAccountWithMembers(
        account: event.account,
        members: event.members,
      );
      emit(AccountOperationSuccess('Compte créé avec succès. ID: $accountId'));
    } catch (e, stackTrace) {
      _errorService.logError(
        'AccountBloc',
        'Error creating account with members: $e',
        stackTrace,
      );
      emit(const AccountError('Impossible de créer le compte'));
    }
  }

  Future<void> _onAddMemberToAccount(
    AddMemberToAccount event,
    Emitter<AccountState> emit,
  ) async {
    try {
      emit(AccountLoading());
      await _repository.addMemberToAccount(event.accountId, event.member);
      emit(AccountOperationSuccess('Membre ajouté avec succès'));
    } catch (e, stackTrace) {
      _errorService.logError(
        'AccountBloc',
        'Error adding member: $e',
        stackTrace,
      );
      emit(const AccountError('Impossible d\'ajouter le membre'));
    }
  }

  Future<void> _onRemoveMemberFromAccount(
    RemoveMemberFromAccount event,
    Emitter<AccountState> emit,
  ) async {
    try {
      emit(AccountLoading());
      await _repository.removeMemberFromAccount(
        event.accountId,
        event.memberId,
      );
      emit(AccountOperationSuccess('Membre supprimé avec succès'));
    } catch (e, stackTrace) {
      _errorService.logError(
        'AccountBloc',
        'Error removing member: $e',
        stackTrace,
      );
      emit(const AccountError('Impossible de supprimer le membre'));
    }
  }

  @override
  Future<void> close() {
    _accountsSubscription?.cancel();
    return super.close();
  }
}

class _AccountsUpdated extends AccountEvent {
  final List<Account> accounts;
  final String? error;

  const _AccountsUpdated(this.accounts, {this.error});

  @override
  List<Object?> get props => [accounts, error];
}
